2004-08-16 Casper S. Hornstrup <chorns@users.sourceforge.net>
[reactos.git] / reactos / subsys / system / usetup / filesup.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: filesup.c,v 1.11 2004/08/15 22:29:50 chorns Exp $
20 * COPYRIGHT: See COPYING in the top level directory
21 * PROJECT: ReactOS text-mode setup
22 * FILE: subsys/system/usetup/filesup.c
23 * PURPOSE: File support functions
24 * PROGRAMMER: Eric Kohl
25 * Casper S. Hornstrup (chorns@users.sourceforge.net)
26 */
27
28 /* INCLUDES *****************************************************************/
29
30 #include "precomp.h"
31 #include <ntdll/rtl.h>
32
33 #include "usetup.h"
34 #include "filesup.h"
35 #include "cabinet.h"
36
37 #define NDEBUG
38 #include <debug.h>
39
40 /* FUNCTIONS ****************************************************************/
41
42
43 static BOOLEAN HasCurrentCabinet = FALSE;
44 static WCHAR CurrentCabinetName[MAX_PATH];
45
46 NTSTATUS
47 CreateDirectory(PWCHAR DirectoryName)
48 {
49 OBJECT_ATTRIBUTES ObjectAttributes;
50 IO_STATUS_BLOCK IoStatusBlock;
51 UNICODE_STRING PathName;
52 HANDLE DirectoryHandle;
53 NTSTATUS Status;
54
55 RtlCreateUnicodeString(&PathName,
56 DirectoryName);
57 if (PathName.Length > sizeof(WCHAR) &&
58 PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' &&
59 PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.')
60 {
61 PathName.Length -= sizeof(WCHAR);
62 PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
63 }
64
65 if (PathName.Length > sizeof(WCHAR) &&
66 PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'\\')
67 {
68 PathName.Length -= sizeof(WCHAR);
69 PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
70 }
71
72 InitializeObjectAttributes(&ObjectAttributes,
73 &PathName,
74 OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
75 NULL,
76 NULL);
77
78 Status = NtCreateFile(&DirectoryHandle,
79 DIRECTORY_ALL_ACCESS,
80 &ObjectAttributes,
81 &IoStatusBlock,
82 NULL,
83 FILE_ATTRIBUTE_DIRECTORY,
84 0,
85 FILE_CREATE,
86 FILE_SYNCHRONOUS_IO_NONALERT | FILE_DIRECTORY_FILE,
87 NULL,
88 0);
89 if (NT_SUCCESS(Status))
90 {
91 NtClose(DirectoryHandle);
92 }
93
94 RtlFreeUnicodeString(&PathName);
95
96 return(Status);
97 }
98
99
100 NTSTATUS
101 SetupCopyFile(PWCHAR SourceFileName,
102 PWCHAR DestinationFileName)
103 {
104 OBJECT_ATTRIBUTES ObjectAttributes;
105 HANDLE FileHandleSource;
106 HANDLE FileHandleDest;
107 IO_STATUS_BLOCK IoStatusBlock;
108 FILE_STANDARD_INFORMATION FileStandard;
109 FILE_BASIC_INFORMATION FileBasic;
110 FILE_POSITION_INFORMATION FilePosition;
111 PUCHAR Buffer;
112 ULONG RegionSize;
113 UNICODE_STRING FileName;
114 NTSTATUS Status;
115
116 Buffer = NULL;
117
118 RtlInitUnicodeString(&FileName,
119 SourceFileName);
120
121 InitializeObjectAttributes(&ObjectAttributes,
122 &FileName,
123 OBJ_CASE_INSENSITIVE,
124 NULL,
125 NULL);
126
127 Status = NtOpenFile(&FileHandleSource,
128 FILE_READ_ACCESS,
129 &ObjectAttributes,
130 &IoStatusBlock,
131 FILE_SHARE_READ,
132 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
133 if (!NT_SUCCESS(Status))
134 {
135 return(Status);
136 }
137
138 Status = NtQueryInformationFile(FileHandleSource,
139 &IoStatusBlock,
140 &FileStandard,
141 sizeof(FILE_STANDARD_INFORMATION),
142 FileStandardInformation);
143 if (!NT_SUCCESS(Status))
144 {
145 NtClose(FileHandleSource);
146 return(Status);
147 }
148
149 Status = NtQueryInformationFile(FileHandleSource,
150 &IoStatusBlock,&FileBasic,
151 sizeof(FILE_BASIC_INFORMATION),
152 FileBasicInformation);
153 if (!NT_SUCCESS(Status))
154 {
155 NtClose(FileHandleSource);
156 return(Status);
157 }
158
159 RtlInitUnicodeString(&FileName,
160 DestinationFileName);
161
162 InitializeObjectAttributes(&ObjectAttributes,
163 &FileName,
164 OBJ_CASE_INSENSITIVE,
165 NULL,
166 NULL);
167
168 Status = NtCreateFile(&FileHandleDest,
169 FILE_WRITE_ACCESS,
170 &ObjectAttributes,
171 &IoStatusBlock,
172 NULL,
173 FILE_ATTRIBUTE_NORMAL,
174 0,
175 FILE_OVERWRITE_IF,
176 FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
177 NULL,
178 0);
179 if (!NT_SUCCESS(Status))
180 {
181 NtClose(FileHandleSource);
182 return(Status);
183 }
184
185 FilePosition.CurrentByteOffset.QuadPart = 0;
186
187 Status = NtSetInformationFile(FileHandleSource,
188 &IoStatusBlock,
189 &FilePosition,
190 sizeof(FILE_POSITION_INFORMATION),
191 FilePositionInformation);
192 if (!NT_SUCCESS(Status))
193 {
194 NtClose(FileHandleSource);
195 NtClose(FileHandleDest);
196 return(Status);
197 }
198
199 Status = NtSetInformationFile(FileHandleDest,
200 &IoStatusBlock,
201 &FilePosition,
202 sizeof(FILE_POSITION_INFORMATION),
203 FilePositionInformation);
204 if (!NT_SUCCESS(Status))
205 {
206 NtClose(FileHandleSource);
207 NtClose(FileHandleDest);
208 return(Status);
209 }
210
211 RegionSize = PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
212 if (RegionSize > 0x100000)
213 {
214 RegionSize = 0x100000;
215 }
216 Status = NtAllocateVirtualMemory(NtCurrentProcess(),
217 (PVOID *)&Buffer,
218 2,
219 &RegionSize,
220 MEM_RESERVE | MEM_COMMIT,
221 PAGE_READWRITE);
222 if (!NT_SUCCESS(Status))
223 {
224 NtClose(FileHandleSource);
225 NtClose(FileHandleDest);
226 return(Status);
227 }
228
229 while (TRUE)
230 {
231 Status = NtReadFile(FileHandleSource,
232 NULL,
233 NULL,
234 NULL,
235 &IoStatusBlock,
236 Buffer,
237 RegionSize,
238 NULL,
239 NULL);
240 if (!NT_SUCCESS(Status))
241 {
242 NtFreeVirtualMemory(NtCurrentProcess(),
243 (PVOID *)&Buffer,
244 &RegionSize,
245 MEM_RELEASE);
246 if (Status == STATUS_END_OF_FILE)
247 {
248 DPRINT("STATUS_END_OF_FILE\n");
249 break;
250 }
251 NtClose(FileHandleSource);
252 NtClose(FileHandleDest);
253 return(Status);
254 }
255
256 DPRINT("Bytes read %lu\n", IoStatusBlock.Information);
257
258 Status = NtWriteFile(FileHandleDest,
259 NULL,
260 NULL,
261 NULL,
262 &IoStatusBlock,
263 Buffer,
264 IoStatusBlock.Information,
265 NULL,
266 NULL);
267 if (!NT_SUCCESS(Status))
268 {
269 NtFreeVirtualMemory(NtCurrentProcess(),
270 (PVOID *)&Buffer,
271 &RegionSize,
272 MEM_RELEASE);
273 NtClose(FileHandleSource);
274 NtClose(FileHandleDest);
275 return(Status);
276 }
277 }
278
279
280 /* Copy file date/time from source file */
281 Status = NtSetInformationFile(FileHandleDest,
282 &IoStatusBlock,
283 &FileBasic,
284 sizeof(FILE_BASIC_INFORMATION),
285 FileBasicInformation);
286 if (!NT_SUCCESS(Status))
287 {
288 DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
289 }
290
291 NtClose(FileHandleSource);
292 NtClose(FileHandleDest);
293
294 return(Status);
295 }
296
297
298 NTSTATUS
299 SetupExtractFile(PWCHAR CabinetFileName,
300 PWCHAR SourceFileName,
301 PWCHAR DestinationPathName)
302 {
303 ULONG CabStatus;
304
305 DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
306 CabinetFileName, SourceFileName, DestinationPathName);
307
308 if (HasCurrentCabinet)
309 {
310 DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName);
311 }
312
313 if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0))
314 {
315 DPRINT("Using same cabinet as last time\n");
316 }
317 else
318 {
319 DPRINT("Using new cabinet\n");
320
321 if (HasCurrentCabinet)
322 {
323 CabinetCleanup();
324 }
325
326 wcscpy(CurrentCabinetName, CabinetFileName);
327
328 CabinetInitialize();
329 CabinetSetEventHandlers(NULL, NULL, NULL);
330 CabinetSetCabinetName(CabinetFileName);
331
332 CabStatus = CabinetOpen();
333 if (CabStatus == CAB_STATUS_SUCCESS)
334 {
335 DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
336 HasCurrentCabinet = TRUE;
337 }
338 else
339 {
340 DPRINT("Cannot open cabinet (%d)\n", CabStatus);
341 return STATUS_UNSUCCESSFUL;
342 }
343 }
344
345 CabinetSetDestinationPath(DestinationPathName);
346 CabStatus = CabinetExtractFile(SourceFileName);
347 if (CabStatus != CAB_STATUS_SUCCESS)
348 {
349 DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
350 return STATUS_UNSUCCESSFUL;
351 }
352
353 return STATUS_SUCCESS;
354 }
355
356
357 BOOLEAN
358 DoesFileExist(PWSTR PathName,
359 PWSTR FileName)
360 {
361 OBJECT_ATTRIBUTES ObjectAttributes;
362 IO_STATUS_BLOCK IoStatusBlock;
363 UNICODE_STRING Name;
364 WCHAR FullName[MAX_PATH];
365 HANDLE FileHandle;
366 NTSTATUS Status;
367
368 wcscpy(FullName, PathName);
369 if (FileName != NULL)
370 {
371 if (FileName[0] != L'\\')
372 wcscat(FullName, L"\\");
373 wcscat(FullName, FileName);
374 }
375
376 RtlInitUnicodeString(&Name,
377 FullName);
378
379 InitializeObjectAttributes(&ObjectAttributes,
380 &Name,
381 OBJ_CASE_INSENSITIVE,
382 NULL,
383 NULL);
384
385 Status = NtOpenFile(&FileHandle,
386 FILE_READ_ACCESS,
387 &ObjectAttributes,
388 &IoStatusBlock,
389 0,
390 FILE_SYNCHRONOUS_IO_NONALERT);
391 if (!NT_SUCCESS(Status))
392 {
393 return(FALSE);
394 }
395
396 NtClose(FileHandle);
397
398 return(TRUE);
399 }
400
401 /* EOF */