Sync with trunk (r47116), hopefully without breaking anything.
[reactos.git] / base / setup / 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 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: subsys/system/usetup/filesup.c
22 * PURPOSE: File support functions
23 * PROGRAMMER: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
25 */
26
27 /* INCLUDES *****************************************************************/
28
29 #include "usetup.h"
30
31 #define NDEBUG
32 #include <debug.h>
33
34 /* FUNCTIONS ****************************************************************/
35
36 static BOOLEAN HasCurrentCabinet = FALSE;
37 static WCHAR CurrentCabinetName[MAX_PATH];
38
39 NTSTATUS
40 SetupCreateDirectory(PWCHAR DirectoryName)
41 {
42 OBJECT_ATTRIBUTES ObjectAttributes;
43 IO_STATUS_BLOCK IoStatusBlock;
44 UNICODE_STRING PathName;
45 HANDLE DirectoryHandle;
46 NTSTATUS Status;
47
48 RtlCreateUnicodeString(&PathName,
49 DirectoryName);
50 if (PathName.Length > sizeof(WCHAR) &&
51 PathName.Buffer[PathName.Length / sizeof(WCHAR) - 2] == L'\\' &&
52 PathName.Buffer[PathName.Length / sizeof(WCHAR) - 1] == L'.')
53 {
54 PathName.Length -= sizeof(WCHAR);
55 PathName.Buffer[PathName.Length / sizeof(WCHAR)] = 0;
56 }
57
58 if (PathName.Length > sizeof(WCHAR) &&
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 InitializeObjectAttributes(&ObjectAttributes,
66 &PathName,
67 OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
68 NULL,
69 NULL);
70
71 Status = NtCreateFile(&DirectoryHandle,
72 DIRECTORY_ALL_ACCESS,
73 &ObjectAttributes,
74 &IoStatusBlock,
75 NULL,
76 FILE_ATTRIBUTE_DIRECTORY,
77 FILE_SHARE_READ | FILE_SHARE_WRITE,
78 FILE_OPEN_IF,
79 FILE_DIRECTORY_FILE,
80 NULL,
81 0);
82 if (NT_SUCCESS(Status))
83 {
84 NtClose(DirectoryHandle);
85 }
86
87 RtlFreeUnicodeString(&PathName);
88
89 return(Status);
90 }
91
92
93 NTSTATUS
94 SetupCopyFile(PWCHAR SourceFileName,
95 PWCHAR DestinationFileName)
96 {
97 OBJECT_ATTRIBUTES ObjectAttributes;
98 HANDLE FileHandleSource;
99 HANDLE FileHandleDest;
100 static IO_STATUS_BLOCK IoStatusBlock;
101 FILE_STANDARD_INFORMATION FileStandard;
102 FILE_BASIC_INFORMATION FileBasic;
103 ULONG RegionSize;
104 UNICODE_STRING FileName;
105 NTSTATUS Status;
106 PVOID SourceFileMap = 0;
107 HANDLE SourceFileSection;
108 SIZE_T SourceSectionSize = 0;
109 LARGE_INTEGER ByteOffset;
110
111 #ifdef __REACTOS__
112 RtlInitUnicodeString(&FileName,
113 SourceFileName);
114
115 InitializeObjectAttributes(&ObjectAttributes,
116 &FileName,
117 OBJ_CASE_INSENSITIVE,
118 NULL,
119 NULL);
120
121 Status = NtOpenFile(&FileHandleSource,
122 GENERIC_READ,
123 &ObjectAttributes,
124 &IoStatusBlock,
125 FILE_SHARE_READ,
126 FILE_SEQUENTIAL_ONLY);
127 if(!NT_SUCCESS(Status))
128 {
129 DPRINT1("NtOpenFile failed: %x\n", Status);
130 goto done;
131 }
132 #else
133 FileHandleSource = CreateFileW(SourceFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, 0, NULL);
134 if (FileHandleSource == INVALID_HANDLE_VALUE)
135 {
136 Status = STATUS_UNSUCCESSFUL;
137 goto done;
138 }
139 #endif
140
141 Status = NtQueryInformationFile(FileHandleSource,
142 &IoStatusBlock,
143 &FileStandard,
144 sizeof(FILE_STANDARD_INFORMATION),
145 FileStandardInformation);
146 if(!NT_SUCCESS(Status))
147 {
148 DPRINT1("NtQueryInformationFile failed: %x\n", Status);
149 goto closesrc;
150 }
151 Status = NtQueryInformationFile(FileHandleSource,
152 &IoStatusBlock,&FileBasic,
153 sizeof(FILE_BASIC_INFORMATION),
154 FileBasicInformation);
155 if(!NT_SUCCESS(Status))
156 {
157 DPRINT1("NtQueryInformationFile failed: %x\n", Status);
158 goto closesrc;
159 }
160
161 Status = NtCreateSection( &SourceFileSection,
162 SECTION_MAP_READ,
163 NULL,
164 NULL,
165 PAGE_READONLY,
166 SEC_COMMIT,
167 FileHandleSource);
168 if(!NT_SUCCESS(Status))
169 {
170 DPRINT1("NtCreateSection failed: %x\n", Status);
171 goto closesrc;
172 }
173
174 Status = NtMapViewOfSection( SourceFileSection,
175 NtCurrentProcess(),
176 &SourceFileMap,
177 0,
178 0,
179 NULL,
180 &SourceSectionSize,
181 ViewUnmap,
182 0,
183 PAGE_READONLY );
184 if(!NT_SUCCESS(Status))
185 {
186 DPRINT1("NtMapViewOfSection failed: %x\n", Status);
187 goto closesrcsec;
188 }
189
190 RtlInitUnicodeString(&FileName,
191 DestinationFileName);
192
193 InitializeObjectAttributes(&ObjectAttributes,
194 &FileName,
195 OBJ_CASE_INSENSITIVE,
196 NULL,
197 NULL);
198
199 Status = NtCreateFile(&FileHandleDest,
200 GENERIC_WRITE,
201 &ObjectAttributes,
202 &IoStatusBlock,
203 NULL,
204 FILE_ATTRIBUTE_NORMAL,
205 0,
206 FILE_OVERWRITE_IF,
207 FILE_NO_INTERMEDIATE_BUFFERING |
208 FILE_SEQUENTIAL_ONLY |
209 FILE_SYNCHRONOUS_IO_NONALERT,
210 NULL,
211 0);
212 if(!NT_SUCCESS(Status))
213 {
214 DPRINT1("NtCreateFile failed: %x\n", Status);
215 goto unmapsrcsec;
216 }
217
218 RegionSize = (ULONG)PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
219 IoStatusBlock.Status = 0;
220 ByteOffset.QuadPart = 0;
221 Status = NtWriteFile(FileHandleDest,
222 NULL,
223 NULL,
224 NULL,
225 &IoStatusBlock,
226 SourceFileMap,
227 RegionSize,
228 &ByteOffset,
229 NULL);
230 if(!NT_SUCCESS(Status))
231 {
232 DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize);
233 goto closedest;
234 }
235 /* Copy file date/time from source file */
236 Status = NtSetInformationFile(FileHandleDest,
237 &IoStatusBlock,
238 &FileBasic,
239 sizeof(FILE_BASIC_INFORMATION),
240 FileBasicInformation);
241 if(!NT_SUCCESS(Status))
242 {
243 DPRINT1("NtSetInformationFile failed: %x\n", Status);
244 goto closedest;
245 }
246
247 /* shorten the file back to it's real size after completing the write */
248 Status = NtSetInformationFile(FileHandleDest,
249 &IoStatusBlock,
250 &FileStandard.EndOfFile,
251 sizeof(FILE_END_OF_FILE_INFORMATION),
252 FileEndOfFileInformation);
253
254 if(!NT_SUCCESS(Status))
255 {
256 DPRINT1("NtSetInformationFile failed: %x\n", Status);
257 }
258
259 closedest:
260 NtClose(FileHandleDest);
261 unmapsrcsec:
262 NtUnmapViewOfSection( NtCurrentProcess(), SourceFileMap );
263 closesrcsec:
264 NtClose(SourceFileSection);
265 closesrc:
266 NtClose(FileHandleSource);
267 done:
268 return(Status);
269 }
270
271 #ifdef __REACTOS__
272 NTSTATUS
273 SetupExtractFile(PWCHAR CabinetFileName,
274 PWCHAR SourceFileName,
275 PWCHAR DestinationPathName)
276 {
277 ULONG CabStatus;
278 CAB_SEARCH Search;
279
280 DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
281 CabinetFileName, SourceFileName, DestinationPathName);
282
283 if (HasCurrentCabinet)
284 {
285 DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName);
286 }
287
288 if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0))
289 {
290 DPRINT("Using same cabinet as last time\n");
291 }
292 else
293 {
294 DPRINT("Using new cabinet\n");
295
296 if (HasCurrentCabinet)
297 {
298 CabinetCleanup();
299 }
300
301 wcscpy(CurrentCabinetName, CabinetFileName);
302
303 CabinetInitialize();
304 CabinetSetEventHandlers(NULL, NULL, NULL);
305 CabinetSetCabinetName(CabinetFileName);
306
307 CabStatus = CabinetOpen();
308 if (CabStatus == CAB_STATUS_SUCCESS)
309 {
310 DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
311 HasCurrentCabinet = TRUE;
312 }
313 else
314 {
315 DPRINT("Cannot open cabinet (%d)\n", CabStatus);
316 return STATUS_UNSUCCESSFUL;
317 }
318 }
319
320 CabinetSetDestinationPath(DestinationPathName);
321 CabinetFindFirst( SourceFileName, &Search );
322 CabStatus = CabinetExtractFile(&Search);
323 if (CabStatus != CAB_STATUS_SUCCESS)
324 {
325 DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
326 return STATUS_UNSUCCESSFUL;
327 }
328
329 return STATUS_SUCCESS;
330 }
331 #endif
332
333 BOOLEAN
334 DoesFileExist(PWSTR PathName,
335 PWSTR FileName)
336 {
337 OBJECT_ATTRIBUTES ObjectAttributes;
338 IO_STATUS_BLOCK IoStatusBlock;
339 UNICODE_STRING Name;
340 WCHAR FullName[MAX_PATH];
341 HANDLE FileHandle;
342 NTSTATUS Status;
343
344 wcscpy(FullName, PathName);
345 if (FileName != NULL)
346 {
347 if (FileName[0] != L'\\')
348 wcscat(FullName, L"\\");
349 wcscat(FullName, FileName);
350 }
351
352 RtlInitUnicodeString(&Name,
353 FullName);
354
355 InitializeObjectAttributes(&ObjectAttributes,
356 &Name,
357 OBJ_CASE_INSENSITIVE,
358 NULL,
359 NULL);
360
361 Status = NtOpenFile(&FileHandle,
362 GENERIC_READ,
363 &ObjectAttributes,
364 &IoStatusBlock,
365 0,
366 FILE_SYNCHRONOUS_IO_NONALERT);
367 if (!NT_SUCCESS(Status))
368 {
369 return(FALSE);
370 }
371
372 NtClose(FileHandle);
373
374 return(TRUE);
375 }
376
377 /* EOF */