[SETUP] Remove myself from the 1st stage setup code
[reactos.git] / base / setup / usetup / filequeue.c
1 /*
2 * ReactOS kernel
3 * Copyright (C) 2002 ReactOS Team
4 *
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.
9 *
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.
14 *
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.
18 */
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)
24 */
25
26 /* INCLUDES *****************************************************************/
27
28 #include "usetup.h"
29
30 #define NDEBUG
31 #include <debug.h>
32
33 /* INCLUDES *****************************************************************/
34
35 typedef struct _QUEUEENTRY
36 {
37 struct _QUEUEENTRY *Prev;
38 struct _QUEUEENTRY *Next;
39
40 PWSTR SourceCabinet; /* May be NULL if the file is not in a cabinet */
41 PWSTR SourceRootPath;
42 PWSTR SourcePath;
43 PWSTR SourceFilename;
44 PWSTR TargetDirectory;
45 PWSTR TargetFilename;
46 } QUEUEENTRY, *PQUEUEENTRY;
47
48
49 typedef struct _FILEQUEUEHEADER
50 {
51 PQUEUEENTRY CopyHead;
52 PQUEUEENTRY CopyTail;
53 ULONG CopyCount;
54 } FILEQUEUEHEADER, *PFILEQUEUEHEADER;
55
56
57 /* FUNCTIONS ****************************************************************/
58
59 HSPFILEQ
60 WINAPI
61 SetupOpenFileQueue(VOID)
62 {
63 PFILEQUEUEHEADER QueueHeader;
64
65 /* Allocate queue header */
66 QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap,
67 0,
68 sizeof(FILEQUEUEHEADER));
69 if (QueueHeader == NULL)
70 return NULL;
71
72 /* Initialize queue header */
73 RtlZeroMemory(QueueHeader,
74 sizeof(FILEQUEUEHEADER));
75
76 return (HSPFILEQ)QueueHeader;
77 }
78
79
80 VOID
81 WINAPI
82 SetupCloseFileQueue(
83 HSPFILEQ QueueHandle)
84 {
85 PFILEQUEUEHEADER QueueHeader;
86 PQUEUEENTRY Entry;
87
88 if (QueueHandle == NULL)
89 return;
90
91 QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
92
93 /* Delete copy queue */
94 Entry = QueueHeader->CopyHead;
95 while (Entry != NULL)
96 {
97 /* Delete all strings */
98 if (Entry->SourceCabinet != NULL)
99 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
100
101 if (Entry->SourceRootPath != NULL)
102 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
103
104 if (Entry->SourcePath != NULL)
105 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
106
107 if (Entry->SourceFilename != NULL)
108 RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
109
110 if (Entry->TargetDirectory != NULL)
111 RtlFreeHeap(ProcessHeap, 0, Entry->TargetDirectory);
112
113 if (Entry->TargetFilename != NULL)
114 RtlFreeHeap(ProcessHeap, 0, Entry->TargetFilename);
115
116 /* Unlink current queue entry */
117 if (Entry->Next != NULL)
118 {
119 QueueHeader->CopyHead = Entry->Next;
120 QueueHeader->CopyHead->Prev = NULL;
121 }
122 else
123 {
124 QueueHeader->CopyHead = NULL;
125 QueueHeader->CopyTail = NULL;
126 }
127
128 /* Delete queue entry */
129 RtlFreeHeap(ProcessHeap, 0, Entry);
130
131 /* Get next queue entry */
132 Entry = QueueHeader->CopyHead;
133 }
134
135 /* Delete queue header */
136 RtlFreeHeap(ProcessHeap, 0, QueueHeader);
137 }
138
139
140 BOOL
141 SetupQueueCopy(
142 HSPFILEQ QueueHandle,
143 PCWSTR SourceCabinet,
144 PCWSTR SourceRootPath,
145 PCWSTR SourcePath,
146 PCWSTR SourceFilename,
147 PCWSTR TargetDirectory,
148 PCWSTR TargetFilename)
149 {
150 PFILEQUEUEHEADER QueueHeader;
151 PQUEUEENTRY Entry;
152 ULONG Length;
153
154 /* SourceCabinet may be NULL */
155 if (QueueHandle == NULL ||
156 SourceRootPath == NULL ||
157 SourceFilename == NULL ||
158 TargetDirectory == NULL)
159 return FALSE;
160
161 QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
162
163 /* Allocate new queue entry */
164 Entry = (PQUEUEENTRY)RtlAllocateHeap(ProcessHeap,
165 0,
166 sizeof(QUEUEENTRY));
167 if (Entry == NULL)
168 return FALSE;
169
170 RtlZeroMemory(Entry,
171 sizeof(QUEUEENTRY));
172
173 /* Copy source cabinet if available */
174 if (SourceCabinet != NULL)
175 {
176 Length = wcslen(SourceCabinet);
177 Entry->SourceCabinet = (WCHAR*)RtlAllocateHeap(ProcessHeap,
178 0,
179 (Length + 1) * sizeof(WCHAR));
180 if (Entry->SourceCabinet == NULL)
181 {
182 RtlFreeHeap(ProcessHeap, 0, Entry);
183 return FALSE;
184 }
185
186 wcsncpy(Entry->SourceCabinet, SourceCabinet, Length);
187 Entry->SourceCabinet[Length] = (WCHAR)0;
188 }
189 else
190 {
191 Entry->SourceCabinet = NULL;
192 }
193
194 /* Copy source root path */
195 Length = wcslen(SourceRootPath);
196 Entry->SourceRootPath = (WCHAR*)RtlAllocateHeap(ProcessHeap,
197 0,
198 (Length + 1) * sizeof(WCHAR));
199 if (Entry->SourceRootPath == NULL)
200 {
201 if (Entry->SourceCabinet != NULL)
202 {
203 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
204 }
205
206 RtlFreeHeap(ProcessHeap, 0, Entry);
207 return FALSE;
208 }
209
210 wcsncpy(Entry->SourceRootPath, SourceRootPath, Length);
211 Entry->SourceRootPath[Length] = (WCHAR)0;
212
213 /* Copy source path */
214 if (SourcePath != NULL)
215 {
216 Length = wcslen(SourcePath);
217 if ((Length > 0) && (SourcePath[Length - 1] == L'\\'))
218 Length--;
219 Entry->SourcePath = (WCHAR*)RtlAllocateHeap(ProcessHeap,
220 0,
221 (Length + 1) * sizeof(WCHAR));
222 if (Entry->SourcePath == NULL)
223 {
224 if (Entry->SourceCabinet != NULL)
225 {
226 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
227 }
228
229 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
230 RtlFreeHeap(ProcessHeap, 0, Entry);
231 return FALSE;
232 }
233
234 wcsncpy(Entry->SourcePath, SourcePath, Length);
235 Entry->SourcePath[Length] = (WCHAR)0;
236 }
237
238 /* Copy source file name */
239 Length = wcslen(SourceFilename);
240 Entry->SourceFilename = (WCHAR*)RtlAllocateHeap(ProcessHeap,
241 0,
242 (Length + 1) * sizeof(WCHAR));
243 if (Entry->SourceFilename == NULL)
244 {
245 if (Entry->SourceCabinet != NULL)
246 {
247 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
248 }
249
250 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
251 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
252 RtlFreeHeap(ProcessHeap, 0, Entry);
253 return FALSE;
254 }
255
256 wcsncpy(Entry->SourceFilename, SourceFilename, Length);
257 Entry->SourceFilename[Length] = (WCHAR)0;
258
259 /* Copy target directory */
260 Length = wcslen(TargetDirectory);
261 if ((Length > 0) && (TargetDirectory[Length - 1] == L'\\'))
262 Length--;
263 Entry->TargetDirectory = (WCHAR*)RtlAllocateHeap(ProcessHeap,
264 0,
265 (Length + 1) * sizeof(WCHAR));
266 if (Entry->TargetDirectory == NULL)
267 {
268 if (Entry->SourceCabinet != NULL)
269 {
270 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
271 }
272
273 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
274 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
275 RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
276 RtlFreeHeap(ProcessHeap, 0, Entry);
277 return FALSE;
278 }
279
280 wcsncpy(Entry->TargetDirectory, TargetDirectory, Length);
281 Entry->TargetDirectory[Length] = (WCHAR)0;
282
283 /* Copy optional target filename */
284 if (TargetFilename != NULL)
285 {
286 Length = wcslen(TargetFilename);
287 Entry->TargetFilename = (WCHAR*)RtlAllocateHeap(ProcessHeap,
288 0,
289 (Length + 1) * sizeof(WCHAR));
290 if (Entry->TargetFilename == NULL)
291 {
292 if (Entry->SourceCabinet != NULL)
293 {
294 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
295 }
296
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);
302 return FALSE;
303 }
304
305 wcsncpy(Entry->TargetFilename, TargetFilename, Length);
306 Entry->TargetFilename[Length] = (WCHAR)0;
307 }
308
309 /* Append queue entry */
310 if (QueueHeader->CopyHead == NULL) // && QueueHeader->CopyTail == NULL)
311 {
312 Entry->Prev = NULL;
313 Entry->Next = NULL;
314 QueueHeader->CopyHead = Entry;
315 QueueHeader->CopyTail = Entry;
316 }
317 else
318 {
319 Entry->Prev = QueueHeader->CopyTail;
320 Entry->Next = NULL;
321 QueueHeader->CopyTail->Next = Entry;
322 QueueHeader->CopyTail = Entry;
323 }
324
325 QueueHeader->CopyCount++;
326
327 return TRUE;
328 }
329
330
331 BOOL
332 WINAPI
333 SetupCommitFileQueueW(
334 HWND Owner,
335 HSPFILEQ QueueHandle,
336 PSP_FILE_CALLBACK_W MsgHandler,
337 PVOID Context)
338 {
339 WCHAR CabinetName[MAX_PATH];
340 PFILEQUEUEHEADER QueueHeader;
341 PQUEUEENTRY Entry;
342 NTSTATUS Status;
343 PCWSTR TargetRootPath, TargetPath;
344
345 WCHAR FileSrcPath[MAX_PATH];
346 WCHAR FileDstPath[MAX_PATH];
347
348 TargetRootPath = ((PCOPYCONTEXT)Context)->DestinationRootPath;
349 TargetPath = ((PCOPYCONTEXT)Context)->InstallPath;
350
351 if (QueueHandle == NULL)
352 return FALSE;
353
354 QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
355
356 MsgHandler(Context,
357 SPFILENOTIFY_STARTQUEUE,
358 0,
359 0);
360
361 MsgHandler(Context,
362 SPFILENOTIFY_STARTSUBQUEUE,
363 FILEOP_COPY,
364 QueueHeader->CopyCount);
365
366 /* Commit copy queue */
367 Entry = QueueHeader->CopyHead;
368 while (Entry != NULL)
369 {
370 /* Build the full source path */
371 wcscpy(FileSrcPath, Entry->SourceRootPath);
372 if (Entry->SourcePath != NULL)
373 wcscat(FileSrcPath, Entry->SourcePath);
374 wcscat(FileSrcPath, L"\\");
375 wcscat(FileSrcPath, Entry->SourceFilename);
376
377 /* Build the full target path */
378 wcscpy(FileDstPath, TargetRootPath);
379 if (Entry->TargetDirectory[0] == 0)
380 {
381 /* Installation path */
382
383 /* Add the installation path */
384 if (TargetPath != NULL)
385 {
386 if (TargetPath[0] != L'\\')
387 wcscat(FileDstPath, L"\\");
388 wcscat(FileDstPath, TargetPath);
389 }
390 }
391 else if (Entry->TargetDirectory[0] == L'\\')
392 {
393 /* Absolute path */
394 if (Entry->TargetDirectory[1] != 0)
395 wcscat(FileDstPath, Entry->TargetDirectory);
396 }
397 else // if (Entry->TargetDirectory[0] != L'\\')
398 {
399 /* Path relative to the installation path */
400
401 /* Add the installation path */
402 if (TargetPath != NULL)
403 {
404 if (TargetPath[0] != L'\\')
405 wcscat(FileDstPath, L"\\");
406 wcscat(FileDstPath, TargetPath);
407 }
408
409 wcscat(FileDstPath, L"\\");
410 wcscat(FileDstPath, Entry->TargetDirectory);
411 }
412
413 /*
414 * If the file is in a cabinet, use only the destination path.
415 * Otherwise possibly use a different target name.
416 */
417 if (Entry->SourceCabinet == NULL)
418 {
419 wcscat(FileDstPath, L"\\");
420 if (Entry->TargetFilename != NULL)
421 wcscat(FileDstPath, Entry->TargetFilename);
422 else
423 wcscat(FileDstPath, Entry->SourceFilename);
424 }
425
426 /* FIXME: Do it! */
427 DPRINT("Copy: '%S' ==> '%S'\n", FileSrcPath, FileDstPath);
428
429 MsgHandler(Context,
430 SPFILENOTIFY_STARTCOPY,
431 (UINT_PTR)Entry->SourceFilename,
432 FILEOP_COPY);
433
434 if (Entry->SourceCabinet != NULL)
435 {
436 /* Extract the file */
437 wcscpy(CabinetName, Entry->SourceRootPath);
438 if (Entry->SourcePath != NULL)
439 wcscat(CabinetName, Entry->SourcePath);
440 wcscat(CabinetName, L"\\");
441 wcscat(CabinetName, Entry->SourceCabinet);
442 Status = SetupExtractFile(CabinetName, Entry->SourceFilename, FileDstPath);
443 }
444 else
445 {
446 /* Copy the file */
447 Status = SetupCopyFile(FileSrcPath, FileDstPath);
448 }
449
450 if (!NT_SUCCESS(Status))
451 {
452 MsgHandler(Context,
453 SPFILENOTIFY_COPYERROR,
454 (UINT_PTR)Entry->SourceFilename,
455 FILEOP_COPY);
456 }
457 else
458 {
459 MsgHandler(Context,
460 SPFILENOTIFY_ENDCOPY,
461 (UINT_PTR)Entry->SourceFilename,
462 FILEOP_COPY);
463 }
464
465 Entry = Entry->Next;
466 }
467
468 MsgHandler(Context,
469 SPFILENOTIFY_ENDSUBQUEUE,
470 FILEOP_COPY,
471 0);
472
473 MsgHandler(Context,
474 SPFILENOTIFY_ENDQUEUE,
475 0,
476 0);
477
478 return TRUE;
479 }
480
481 /* EOF */