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 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.
19 /* COPYRIGHT: See COPYING in the top level directory
20 * PROJECT: ReactOS text-mode setup
21 * FILE: subsys/system/usetup/filequeue.c
22 * PURPOSE: File queue functions
23 * PROGRAMMER: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
27 /* INCLUDES *****************************************************************/
34 /* INCLUDES *****************************************************************/
36 typedef struct _QUEUEENTRY
38 struct _QUEUEENTRY
*Prev
;
39 struct _QUEUEENTRY
*Next
;
41 PWSTR SourceCabinet
; /* May be NULL if file is not in a cabinet */
45 PWSTR TargetDirectory
;
48 } QUEUEENTRY
, *PQUEUEENTRY
;
51 typedef struct _FILEQUEUEHEADER
56 } FILEQUEUEHEADER
, *PFILEQUEUEHEADER
;
59 /* FUNCTIONS ****************************************************************/
62 SetupOpenFileQueue(VOID
)
64 PFILEQUEUEHEADER QueueHeader
;
66 /* Allocate queue header */
67 QueueHeader
= (PFILEQUEUEHEADER
)RtlAllocateHeap(ProcessHeap
,
69 sizeof(FILEQUEUEHEADER
));
70 if (QueueHeader
== NULL
)
73 /* Initialize queue header */
74 RtlZeroMemory(QueueHeader
,
75 sizeof(FILEQUEUEHEADER
));
78 return((HSPFILEQ
)QueueHeader
);
83 SetupCloseFileQueue(HSPFILEQ QueueHandle
)
85 PFILEQUEUEHEADER QueueHeader
;
88 if (QueueHandle
== NULL
)
91 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
93 /* Delete copy queue */
94 Entry
= QueueHeader
->CopyHead
;
97 /* Delete all strings */
98 if (Entry
->SourceCabinet
!= NULL
)
99 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
100 if (Entry
->SourceRootPath
!= NULL
)
101 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
102 if (Entry
->SourcePath
!= NULL
)
103 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
104 if (Entry
->SourceFilename
!= NULL
)
105 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
106 if (Entry
->TargetDirectory
!= NULL
)
107 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
108 if (Entry
->TargetFilename
!= NULL
)
109 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetFilename
);
111 /* Unlink current queue entry */
112 if (Entry
->Next
!= NULL
)
114 QueueHeader
->CopyHead
= Entry
->Next
;
115 QueueHeader
->CopyHead
->Prev
= NULL
;
119 QueueHeader
->CopyHead
= NULL
;
120 QueueHeader
->CopyTail
= NULL
;
123 /* Delete queue entry */
124 RtlFreeHeap(ProcessHeap
, 0, Entry
);
126 /* Get next queue entry */
127 Entry
= QueueHeader
->CopyHead
;
130 /* Delete queue header */
131 RtlFreeHeap(ProcessHeap
,
138 SetupQueueCopy(HSPFILEQ QueueHandle
,
139 PCWSTR SourceCabinet
,
140 PCWSTR SourceRootPath
,
142 PCWSTR SourceFilename
,
143 PCWSTR TargetDirectory
,
144 PCWSTR TargetFilename
)
146 PFILEQUEUEHEADER QueueHeader
;
150 /* SourceCabinet may be NULL */
151 if (QueueHandle
== NULL
||
152 SourceRootPath
== NULL
||
153 SourceFilename
== NULL
||
154 TargetDirectory
== NULL
)
157 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
159 /* Allocate new queue entry */
160 Entry
= (PQUEUEENTRY
)RtlAllocateHeap(ProcessHeap
,
169 /* Copy source cabinet if available */
170 if (SourceCabinet
!= NULL
)
172 Length
= wcslen(SourceCabinet
);
173 Entry
->SourceCabinet
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
175 (Length
+ 1) * sizeof(WCHAR
));
176 if (Entry
->SourceCabinet
== NULL
)
178 RtlFreeHeap(ProcessHeap
, 0, Entry
);
181 wcsncpy(Entry
->SourceCabinet
, SourceCabinet
, Length
);
182 Entry
->SourceCabinet
[Length
] = (WCHAR
)0;
186 Entry
->SourceCabinet
= NULL
;
189 /* Copy source root path */
190 Length
= wcslen(SourceRootPath
);
191 Entry
->SourceRootPath
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
193 (Length
+ 1) * sizeof(WCHAR
));
194 if (Entry
->SourceRootPath
== NULL
)
196 if (Entry
->SourceCabinet
!= NULL
)
198 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
200 RtlFreeHeap(ProcessHeap
, 0, Entry
);
203 wcsncpy(Entry
->SourceRootPath
, SourceRootPath
, Length
);
204 Entry
->SourceRootPath
[Length
] = (WCHAR
)0;
206 /* Copy source path */
207 if (SourcePath
!= NULL
)
209 Length
= wcslen(SourcePath
);
210 Entry
->SourcePath
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
212 (Length
+ 1) * sizeof(WCHAR
));
213 if (Entry
->SourcePath
== NULL
)
215 if (Entry
->SourceCabinet
!= NULL
)
217 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
219 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
220 RtlFreeHeap(ProcessHeap
, 0, Entry
);
223 wcsncpy(Entry
->SourcePath
, SourcePath
, Length
);
224 Entry
->SourcePath
[Length
] = (WCHAR
)0;
227 /* Copy source file name */
228 Length
= wcslen(SourceFilename
);
229 Entry
->SourceFilename
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
231 (Length
+ 1) * sizeof(WCHAR
));
232 if (Entry
->SourceFilename
== NULL
)
234 if (Entry
->SourceCabinet
!= NULL
)
236 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
238 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
239 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
240 RtlFreeHeap(ProcessHeap
, 0, Entry
);
243 wcsncpy(Entry
->SourceFilename
, SourceFilename
, Length
);
244 Entry
->SourceFilename
[Length
] = (WCHAR
)0;
246 /* Copy target directory */
247 Length
= wcslen(TargetDirectory
);
248 if (TargetDirectory
[Length
] == '\\')
250 Entry
->TargetDirectory
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
252 (Length
+ 1) * sizeof(WCHAR
));
253 if (Entry
->TargetDirectory
== NULL
)
255 if (Entry
->SourceCabinet
!= NULL
)
257 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
259 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
260 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
261 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
262 RtlFreeHeap(ProcessHeap
, 0, Entry
);
265 wcsncpy(Entry
->TargetDirectory
, TargetDirectory
, Length
);
266 Entry
->TargetDirectory
[Length
] = (WCHAR
)0;
268 /* Copy optional target filename */
269 if (TargetFilename
!= NULL
)
271 Length
= wcslen(TargetFilename
);
272 Entry
->TargetFilename
= (WCHAR
*) RtlAllocateHeap(ProcessHeap
,
274 (Length
+ 1) * sizeof(WCHAR
));
275 if (Entry
->TargetFilename
== NULL
)
277 if (Entry
->SourceCabinet
!= NULL
)
279 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceCabinet
);
281 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceRootPath
);
282 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourcePath
);
283 RtlFreeHeap(ProcessHeap
, 0, Entry
->SourceFilename
);
284 RtlFreeHeap(ProcessHeap
, 0, Entry
->TargetDirectory
);
285 RtlFreeHeap(ProcessHeap
, 0, Entry
);
288 wcsncpy(Entry
->TargetFilename
, TargetFilename
, Length
);
289 Entry
->TargetFilename
[Length
] = (WCHAR
)0;
292 /* Append queue entry */
293 if (QueueHeader
->CopyHead
== NULL
) // && QueueHeader->CopyTail == NULL)
297 QueueHeader
->CopyHead
= Entry
;
298 QueueHeader
->CopyTail
= Entry
;
302 Entry
->Prev
= QueueHeader
->CopyTail
;
304 QueueHeader
->CopyTail
->Next
= Entry
;
305 QueueHeader
->CopyTail
= Entry
;
307 QueueHeader
->CopyCount
++;
314 SetupCommitFileQueueW(HWND Owner
,
315 HSPFILEQ QueueHandle
,
316 PSP_FILE_CALLBACK_W MsgHandler
,
319 WCHAR CabinetName
[MAX_PATH
];
320 PFILEQUEUEHEADER QueueHeader
;
323 PCWSTR TargetRootPath
, TargetPath
;
325 WCHAR FileSrcPath
[MAX_PATH
];
326 WCHAR FileDstPath
[MAX_PATH
];
328 TargetRootPath
= ((PCOPYCONTEXT
)Context
)->DestinationRootPath
;
329 TargetPath
= ((PCOPYCONTEXT
)Context
)->InstallPath
;
331 if (QueueHandle
== NULL
)
334 QueueHeader
= (PFILEQUEUEHEADER
)QueueHandle
;
337 SPFILENOTIFY_STARTQUEUE
,
342 SPFILENOTIFY_STARTSUBQUEUE
,
344 QueueHeader
->CopyCount
);
346 /* Commit copy queue */
347 Entry
= QueueHeader
->CopyHead
;
348 while (Entry
!= NULL
)
350 wcscpy(FileSrcPath
, Entry
->SourceRootPath
);
351 if (Entry
->SourcePath
!= NULL
)
352 wcscat(FileSrcPath
, Entry
->SourcePath
);
353 wcscat(FileSrcPath
, L
"\\");
354 wcscat(FileSrcPath
, Entry
->SourceFilename
);
356 /* Build the full target path */
357 wcscpy(FileDstPath
, TargetRootPath
);
358 if (Entry
->TargetDirectory
[0] == L
'\\')
360 wcscat(FileDstPath
, Entry
->TargetDirectory
);
364 if (TargetPath
!= NULL
)
366 if (TargetPath
[0] != L
'\\')
367 wcscat(FileDstPath
, L
"\\");
368 wcscat(FileDstPath
, TargetPath
);
370 wcscat(FileDstPath
, L
"\\");
371 wcscat(FileDstPath
, Entry
->TargetDirectory
);
374 /* Use only the destination path if the file is in a cabinet */
375 if (Entry
->SourceCabinet
== NULL
)
377 wcscat(FileDstPath
, L
"\\");
378 if (Entry
->TargetFilename
!= NULL
)
379 wcscat(FileDstPath
, Entry
->TargetFilename
);
381 wcscat(FileDstPath
, Entry
->SourceFilename
);
385 DPRINT("'%S' ==> '%S'\n",
390 SPFILENOTIFY_STARTCOPY
,
391 (UINT_PTR
)Entry
->SourceFilename
,
394 if (Entry
->SourceCabinet
!= NULL
)
396 /* Extract the file */
397 wcscpy(CabinetName
, Entry
->SourceRootPath
);
398 if (Entry
->SourcePath
!= NULL
)
399 wcscat(CabinetName
, Entry
->SourcePath
);
400 wcscat(CabinetName
, L
"\\");
401 wcscat(CabinetName
, Entry
->SourceCabinet
);
402 Status
= SetupExtractFile(CabinetName
, Entry
->SourceFilename
, FileDstPath
);
407 Status
= SetupCopyFile(FileSrcPath
, FileDstPath
);
409 if (!NT_SUCCESS(Status
))
412 SPFILENOTIFY_COPYERROR
,
413 (UINT_PTR
)Entry
->SourceFilename
,
420 SPFILENOTIFY_ENDCOPY
,
421 (UINT_PTR
)Entry
->SourceFilename
,
429 SPFILENOTIFY_ENDSUBQUEUE
,
434 SPFILENOTIFY_ENDQUEUE
,