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/filesup.c
22 * PURPOSE: File support functions
23 * PROGRAMMER: Eric Kohl
24 * Casper S. Hornstrup (chorns@users.sourceforge.net)
27 /* INCLUDES *****************************************************************/
34 /* FUNCTIONS ****************************************************************/
36 static BOOLEAN HasCurrentCabinet
= FALSE
;
37 static WCHAR CurrentCabinetName
[MAX_PATH
];
38 static CAB_SEARCH Search
;
44 OBJECT_ATTRIBUTES ObjectAttributes
;
45 IO_STATUS_BLOCK IoStatusBlock
;
46 UNICODE_STRING PathName
;
47 HANDLE DirectoryHandle
;
50 RtlCreateUnicodeString(&PathName
,
52 if (PathName
.Length
> sizeof(WCHAR
) &&
53 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 2] == L
'\\' &&
54 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 1] == L
'.')
56 PathName
.Length
-= sizeof(WCHAR
);
57 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
)] = 0;
60 if (PathName
.Length
> sizeof(WCHAR
) &&
61 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 1] == L
'\\')
63 PathName
.Length
-= sizeof(WCHAR
);
64 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
)] = 0;
67 InitializeObjectAttributes(&ObjectAttributes
,
69 OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
,
73 Status
= NtCreateFile(&DirectoryHandle
,
78 FILE_ATTRIBUTE_DIRECTORY
,
79 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
84 if (NT_SUCCESS(Status
))
86 NtClose(DirectoryHandle
);
89 RtlFreeUnicodeString(&PathName
);
97 PWCHAR SourceFileName
,
98 PWCHAR DestinationFileName
)
100 OBJECT_ATTRIBUTES ObjectAttributes
;
101 HANDLE FileHandleSource
;
102 HANDLE FileHandleDest
;
103 static IO_STATUS_BLOCK IoStatusBlock
;
104 FILE_STANDARD_INFORMATION FileStandard
;
105 FILE_BASIC_INFORMATION FileBasic
;
107 UNICODE_STRING FileName
;
109 PVOID SourceFileMap
= 0;
110 HANDLE SourceFileSection
;
111 SIZE_T SourceSectionSize
= 0;
112 LARGE_INTEGER ByteOffset
;
115 RtlInitUnicodeString(&FileName
,
118 InitializeObjectAttributes(&ObjectAttributes
,
120 OBJ_CASE_INSENSITIVE
,
124 Status
= NtOpenFile(&FileHandleSource
,
129 FILE_SEQUENTIAL_ONLY
);
130 if (!NT_SUCCESS(Status
))
132 DPRINT1("NtOpenFile failed: %x, %wZ\n", Status
, &FileName
);
136 FileHandleSource
= CreateFileW(SourceFileName
,
143 if (FileHandleSource
== INVALID_HANDLE_VALUE
)
145 Status
= STATUS_UNSUCCESSFUL
;
150 Status
= NtQueryInformationFile(FileHandleSource
,
153 sizeof(FILE_STANDARD_INFORMATION
),
154 FileStandardInformation
);
155 if (!NT_SUCCESS(Status
))
157 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
161 Status
= NtQueryInformationFile(FileHandleSource
,
162 &IoStatusBlock
,&FileBasic
,
163 sizeof(FILE_BASIC_INFORMATION
),
164 FileBasicInformation
);
165 if (!NT_SUCCESS(Status
))
167 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
171 Status
= NtCreateSection(&SourceFileSection
,
178 if (!NT_SUCCESS(Status
))
180 DPRINT1("NtCreateSection failed: %x, %S\n", Status
, SourceFileName
);
184 Status
= NtMapViewOfSection(SourceFileSection
,
194 if (!NT_SUCCESS(Status
))
196 DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status
, SourceFileName
);
200 RtlInitUnicodeString(&FileName
,
201 DestinationFileName
);
203 InitializeObjectAttributes(&ObjectAttributes
,
205 OBJ_CASE_INSENSITIVE
,
209 Status
= NtCreateFile(&FileHandleDest
,
210 GENERIC_WRITE
| SYNCHRONIZE
,
214 FILE_ATTRIBUTE_NORMAL
,
217 FILE_NO_INTERMEDIATE_BUFFERING
|
218 FILE_SEQUENTIAL_ONLY
|
219 FILE_SYNCHRONOUS_IO_NONALERT
,
222 if (!NT_SUCCESS(Status
))
224 DPRINT1("NtCreateFile failed: %x\n", Status
);
228 RegionSize
= (ULONG
)PAGE_ROUND_UP(FileStandard
.EndOfFile
.u
.LowPart
);
229 IoStatusBlock
.Status
= 0;
230 ByteOffset
.QuadPart
= 0;
231 Status
= NtWriteFile(FileHandleDest
,
240 if (!NT_SUCCESS(Status
))
242 DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status
, IoStatusBlock
.Status
, &IoStatusBlock
, SourceFileMap
, RegionSize
);
246 /* Copy file date/time from source file */
247 Status
= NtSetInformationFile(FileHandleDest
,
250 sizeof(FILE_BASIC_INFORMATION
),
251 FileBasicInformation
);
252 if (!NT_SUCCESS(Status
))
254 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
258 /* shorten the file back to it's real size after completing the write */
259 Status
= NtSetInformationFile(FileHandleDest
,
261 &FileStandard
.EndOfFile
,
262 sizeof(FILE_END_OF_FILE_INFORMATION
),
263 FileEndOfFileInformation
);
264 if (!NT_SUCCESS(Status
))
266 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
270 NtClose(FileHandleDest
);
273 NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap
);
276 NtClose(SourceFileSection
);
279 NtClose(FileHandleSource
);
288 PWCHAR CabinetFileName
,
289 PWCHAR SourceFileName
,
290 PWCHAR DestinationPathName
)
294 DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
295 CabinetFileName
, SourceFileName
, DestinationPathName
);
297 if (HasCurrentCabinet
)
299 DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName
);
302 if ((HasCurrentCabinet
) && (wcscmp(CabinetFileName
, CurrentCabinetName
) == 0))
304 DPRINT("Using same cabinet as last time\n");
306 /* Use our last location because the files should be sequential */
307 CabStatus
= CabinetFindNextFileSequential(SourceFileName
, &Search
);
308 if (CabStatus
!= CAB_STATUS_SUCCESS
)
310 DPRINT("Sequential miss on file: %S\n", SourceFileName
);
312 /* Looks like we got unlucky */
313 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
318 DPRINT("Using new cabinet\n");
320 if (HasCurrentCabinet
)
325 wcscpy(CurrentCabinetName
, CabinetFileName
);
328 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
329 CabinetSetCabinetName(CabinetFileName
);
331 CabStatus
= CabinetOpen();
332 if (CabStatus
== CAB_STATUS_SUCCESS
)
334 DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
335 HasCurrentCabinet
= TRUE
;
339 DPRINT("Cannot open cabinet (%d)\n", CabStatus
);
340 return STATUS_UNSUCCESSFUL
;
343 /* We have to start at the beginning here */
344 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
347 if (CabStatus
!= CAB_STATUS_SUCCESS
)
349 DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName
, CabinetGetCabinetName());
350 return STATUS_UNSUCCESSFUL
;
353 CabinetSetDestinationPath(DestinationPathName
);
354 CabStatus
= CabinetExtractFile(&Search
);
355 if (CabStatus
!= CAB_STATUS_SUCCESS
)
357 DPRINT("Cannot extract file %S (%d)\n", SourceFileName
, CabStatus
);
358 return STATUS_UNSUCCESSFUL
;
361 return STATUS_SUCCESS
;
370 OBJECT_ATTRIBUTES ObjectAttributes
;
371 IO_STATUS_BLOCK IoStatusBlock
;
373 WCHAR FullName
[MAX_PATH
];
377 wcscpy(FullName
, PathName
);
378 if (FileName
!= NULL
)
380 if (FileName
[0] != L
'\\')
381 wcscat(FullName
, L
"\\");
382 wcscat(FullName
, FileName
);
385 RtlInitUnicodeString(&Name
,
388 InitializeObjectAttributes(&ObjectAttributes
,
390 OBJ_CASE_INSENSITIVE
,
394 Status
= NtOpenFile(&FileHandle
,
395 GENERIC_READ
| SYNCHRONIZE
,
399 FILE_SYNCHRONOUS_IO_NONALERT
);
400 if (!NT_SUCCESS(Status
))