- Do only allow to install reactos on disks which are visible by the bios.
[reactos.git] / reactos / subsys / system / 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
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18 */
19 /* $Id$
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)
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <usetup.h>
31
32 #define NDEBUG
33 #include <debug.h>
34
35 /* INCLUDES *****************************************************************/
36
37
38 typedef struct _QUEUEENTRY
39 {
40 struct _QUEUEENTRY *Prev;
41 struct _QUEUEENTRY *Next;
42
43 PWSTR SourceCabinet; /* May be NULL if file is not in a cabinet */
44 PWSTR SourceRootPath;
45 PWSTR SourcePath;
46 PWSTR SourceFilename;
47 PWSTR TargetDirectory;
48 PWSTR TargetFilename;
49
50 } QUEUEENTRY, *PQUEUEENTRY;
51
52
53 typedef struct _FILEQUEUEHEADER
54 {
55 PQUEUEENTRY CopyHead;
56 PQUEUEENTRY CopyTail;
57 ULONG CopyCount;
58 } FILEQUEUEHEADER, *PFILEQUEUEHEADER;
59
60
61 /* FUNCTIONS ****************************************************************/
62
63 HSPFILEQ
64 SetupOpenFileQueue(VOID)
65 {
66 PFILEQUEUEHEADER QueueHeader;
67
68 /* Allocate queue header */
69 QueueHeader = (PFILEQUEUEHEADER)RtlAllocateHeap(ProcessHeap,
70 0,
71 sizeof(FILEQUEUEHEADER));
72 if (QueueHeader == NULL)
73 return(NULL);
74
75 /* Initialize queue header */
76 RtlZeroMemory(QueueHeader,
77 sizeof(FILEQUEUEHEADER));
78
79
80 return((HSPFILEQ)QueueHeader);
81 }
82
83
84 BOOL
85 SetupCloseFileQueue(HSPFILEQ QueueHandle)
86 {
87 PFILEQUEUEHEADER QueueHeader;
88 PQUEUEENTRY Entry;
89
90 if (QueueHandle == NULL)
91 return(FALSE);
92
93 QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
94
95 /* Delete copy queue */
96 Entry = QueueHeader->CopyHead;
97 while (Entry != NULL)
98 {
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);
112
113 /* Unlink current queue entry */
114 if (Entry->Next != NULL)
115 {
116 QueueHeader->CopyHead = Entry->Next;
117 QueueHeader->CopyHead->Prev = NULL;
118 }
119 else
120 {
121 QueueHeader->CopyHead = NULL;
122 QueueHeader->CopyTail = NULL;
123 }
124
125 /* Delete queue entry */
126 RtlFreeHeap(ProcessHeap, 0, Entry);
127
128 /* Get next queue entry */
129 Entry = QueueHeader->CopyHead;
130 }
131
132 /* Delete queue header */
133 RtlFreeHeap(ProcessHeap,
134 0,
135 QueueHeader);
136
137 return(TRUE);
138 }
139
140
141 BOOL
142 SetupQueueCopy(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 = 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 wcsncpy(Entry->SourceCabinet, SourceCabinet, Length);
186 Entry->SourceCabinet[Length] = (WCHAR)0;
187 }
188 else
189 {
190 Entry->SourceCabinet = NULL;
191 }
192
193 /* Copy source root path */
194 Length = wcslen(SourceRootPath);
195 Entry->SourceRootPath = RtlAllocateHeap(ProcessHeap,
196 0,
197 (Length + 1) * sizeof(WCHAR));
198 if (Entry->SourceRootPath == NULL)
199 {
200 if (Entry->SourceCabinet != NULL)
201 {
202 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
203 }
204 RtlFreeHeap(ProcessHeap, 0, Entry);
205 return(FALSE);
206 }
207 wcsncpy(Entry->SourceRootPath, SourceRootPath, Length);
208 Entry->SourceRootPath[Length] = (WCHAR)0;
209
210 /* Copy source path */
211 if (SourcePath != NULL)
212 {
213 Length = wcslen(SourcePath);
214 Entry->SourcePath = RtlAllocateHeap(ProcessHeap,
215 0,
216 (Length + 1) * sizeof(WCHAR));
217 if (Entry->SourcePath == NULL)
218 {
219 if (Entry->SourceCabinet != NULL)
220 {
221 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
222 }
223 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
224 RtlFreeHeap(ProcessHeap, 0, Entry);
225 return(FALSE);
226 }
227 wcsncpy(Entry->SourcePath, SourcePath, Length);
228 Entry->SourcePath[Length] = (WCHAR)0;
229 }
230
231 /* Copy source file name */
232 Length = wcslen(SourceFilename);
233 Entry->SourceFilename = RtlAllocateHeap(ProcessHeap,
234 0,
235 (Length + 1) * sizeof(WCHAR));
236 if (Entry->SourceFilename == NULL)
237 {
238 if (Entry->SourceCabinet != NULL)
239 {
240 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
241 }
242 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
243 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
244 RtlFreeHeap(ProcessHeap, 0, Entry);
245 return(FALSE);
246 }
247 wcsncpy(Entry->SourceFilename, SourceFilename, Length);
248 Entry->SourceFilename[Length] = (WCHAR)0;
249
250 /* Copy target directory */
251 Length = wcslen(TargetDirectory);
252 if (TargetDirectory[Length] == '\\')
253 Length--;
254 Entry->TargetDirectory = RtlAllocateHeap(ProcessHeap,
255 0,
256 (Length + 1) * sizeof(WCHAR));
257 if (Entry->TargetDirectory == NULL)
258 {
259 if (Entry->SourceCabinet != NULL)
260 {
261 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
262 }
263 RtlFreeHeap(ProcessHeap, 0, Entry->SourceRootPath);
264 RtlFreeHeap(ProcessHeap, 0, Entry->SourcePath);
265 RtlFreeHeap(ProcessHeap, 0, Entry->SourceFilename);
266 RtlFreeHeap(ProcessHeap, 0, Entry);
267 return(FALSE);
268 }
269 wcsncpy(Entry->TargetDirectory, TargetDirectory, Length);
270 Entry->TargetDirectory[Length] = (WCHAR)0;
271
272 /* Copy optional target filename */
273 if (TargetFilename != NULL)
274 {
275 Length = wcslen(TargetFilename);
276 Entry->TargetFilename = RtlAllocateHeap(ProcessHeap,
277 0,
278 (Length + 1) * sizeof(WCHAR));
279 if (Entry->TargetFilename == NULL)
280 {
281 if (Entry->SourceCabinet != NULL)
282 {
283 RtlFreeHeap(ProcessHeap, 0, Entry->SourceCabinet);
284 }
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);
290 return(FALSE);
291 }
292 wcsncpy(Entry->TargetFilename, TargetFilename, Length);
293 Entry->TargetFilename[Length] = (WCHAR)0;
294 }
295
296 /* Append queue entry */
297 if (QueueHeader->CopyHead == NULL) // && QueueHeader->CopyTail == NULL)
298 {
299 Entry->Prev = NULL;
300 Entry->Next = NULL;
301 QueueHeader->CopyHead = Entry;
302 QueueHeader->CopyTail = Entry;
303 }
304 else
305 {
306 Entry->Prev = QueueHeader->CopyTail;
307 Entry->Next = NULL;
308 QueueHeader->CopyTail->Next = Entry;
309 QueueHeader->CopyTail = Entry;
310 }
311 QueueHeader->CopyCount++;
312
313 return(TRUE);
314 }
315
316
317 BOOL
318 SetupCommitFileQueue(HSPFILEQ QueueHandle,
319 PCWSTR TargetRootPath,
320 PCWSTR TargetPath,
321 PSP_FILE_CALLBACK MsgHandler,
322 PVOID Context)
323 {
324 WCHAR CabinetName[MAX_PATH];
325 PFILEQUEUEHEADER QueueHeader;
326 PQUEUEENTRY Entry;
327 NTSTATUS Status;
328
329 WCHAR FileSrcPath[MAX_PATH];
330 WCHAR FileDstPath[MAX_PATH];
331
332 if (QueueHandle == NULL)
333 return(FALSE);
334
335 QueueHeader = (PFILEQUEUEHEADER)QueueHandle;
336
337 MsgHandler(Context,
338 SPFILENOTIFY_STARTQUEUE,
339 NULL,
340 NULL);
341
342 MsgHandler(Context,
343 SPFILENOTIFY_STARTSUBQUEUE,
344 (PVOID)FILEOP_COPY,
345 (PVOID)QueueHeader->CopyCount);
346
347 /* Commit copy queue */
348 Entry = QueueHeader->CopyHead;
349 while (Entry != NULL)
350 {
351 wcscpy(FileSrcPath, Entry->SourceRootPath);
352 if (Entry->SourcePath != NULL)
353 wcscat(FileSrcPath, Entry->SourcePath);
354 wcscat(FileSrcPath, L"\\");
355 wcscat(FileSrcPath, Entry->SourceFilename);
356
357 /* Build the full target path */
358 wcscpy(FileDstPath, TargetRootPath);
359 if (Entry->TargetDirectory[0] == L'\\')
360 {
361 wcscat(FileDstPath, Entry->TargetDirectory);
362 }
363 else
364 {
365 if (TargetPath != NULL)
366 {
367 if (TargetPath[0] != L'\\')
368 wcscat(FileDstPath, L"\\");
369 wcscat(FileDstPath, TargetPath);
370 }
371 wcscat(FileDstPath, L"\\");
372 wcscat(FileDstPath, Entry->TargetDirectory);
373 }
374
375 /* Use only the destination path if the file is in a cabinet */
376 if (Entry->SourceCabinet == NULL)
377 {
378 wcscat(FileDstPath, L"\\");
379 if (Entry->TargetFilename != NULL)
380 wcscat(FileDstPath, Entry->TargetFilename);
381 else
382 wcscat(FileDstPath, Entry->SourceFilename);
383 }
384
385 /* FIXME: Do it! */
386 DPRINT("'%S' ==> '%S'\n",
387 FileSrcPath,
388 FileDstPath);
389
390 MsgHandler(Context,
391 SPFILENOTIFY_STARTCOPY,
392 (PVOID)Entry->SourceFilename,
393 (PVOID)FILEOP_COPY);
394
395 if (Entry->SourceCabinet != NULL)
396 {
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);
404 }
405 else
406 {
407 /* Copy the file */
408 Status = SetupCopyFile(FileSrcPath, FileDstPath);
409 }
410 if (!NT_SUCCESS(Status))
411 {
412 MsgHandler(Context,
413 SPFILENOTIFY_COPYERROR,
414 (PVOID)Entry->SourceFilename,
415 (PVOID)FILEOP_COPY);
416
417 }
418 else
419 {
420 MsgHandler(Context,
421 SPFILENOTIFY_ENDCOPY,
422 (PVOID)Entry->SourceFilename,
423 (PVOID)FILEOP_COPY);
424 }
425
426 Entry = Entry->Next;
427 }
428
429 MsgHandler(Context,
430 SPFILENOTIFY_ENDSUBQUEUE,
431 (PVOID)FILEOP_COPY,
432 NULL);
433
434 MsgHandler(Context,
435 SPFILENOTIFY_ENDQUEUE,
436 NULL,
437 NULL);
438
439 return(TRUE);
440 }
441
442 /* EOF */