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
;
42 SetupCreateSingleDirectory(
45 OBJECT_ATTRIBUTES ObjectAttributes
;
46 IO_STATUS_BLOCK IoStatusBlock
;
47 UNICODE_STRING PathName
;
48 HANDLE DirectoryHandle
;
51 RtlCreateUnicodeString(&PathName
,
53 if (PathName
.Length
> sizeof(WCHAR
) &&
54 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 2] == L
'\\' &&
55 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 1] == L
'.')
57 PathName
.Length
-= sizeof(WCHAR
);
58 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
)] = 0;
61 if (PathName
.Length
> sizeof(WCHAR
) &&
62 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 1] == L
'\\')
64 PathName
.Length
-= sizeof(WCHAR
);
65 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
)] = 0;
68 InitializeObjectAttributes(&ObjectAttributes
,
70 OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
,
74 Status
= NtCreateFile(&DirectoryHandle
,
79 FILE_ATTRIBUTE_DIRECTORY
,
80 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
85 if (NT_SUCCESS(Status
))
87 NtClose(DirectoryHandle
);
90 RtlFreeUnicodeString(&PathName
);
101 OBJECT_ATTRIBUTES ObjectAttributes
;
102 IO_STATUS_BLOCK IoStatusBlock
;
107 RtlInitUnicodeString(&Name
,
110 InitializeObjectAttributes(&ObjectAttributes
,
112 OBJ_CASE_INSENSITIVE
,
116 Status
= NtOpenFile(&FileHandle
,
117 GENERIC_READ
| SYNCHRONIZE
,
121 FILE_SYNCHRONOUS_IO_NONALERT
);
122 if (!NT_SUCCESS(Status
))
134 SetupCreateDirectory(
137 PWCHAR PathBuffer
= NULL
;
139 ULONG BackslashCount
;
141 NTSTATUS Status
= STATUS_SUCCESS
;
143 Size
= (wcslen(PathName
) + 1) * sizeof(WCHAR
);
144 PathBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
145 if (PathBuffer
== NULL
)
146 return STATUS_INSUFFICIENT_RESOURCES
;
148 wcscpy(PathBuffer
, PathName
);
149 EndPtr
= PathBuffer
+ wcslen(PathName
);
153 /* Skip the '\Device\HarddiskX\PartitionY\ part */
155 while (Ptr
< EndPtr
&& BackslashCount
< 4)
169 DPRINT("PathBuffer: %S\n", PathBuffer
);
170 if (!DoesPathExist(PathBuffer
))
172 DPRINT("Create: %S\n", PathBuffer
);
173 Status
= SetupCreateSingleDirectory(PathBuffer
);
174 if (!NT_SUCCESS(Status
))
184 if (!DoesPathExist(PathBuffer
))
186 DPRINT("Create: %S\n", PathBuffer
);
187 Status
= SetupCreateSingleDirectory(PathBuffer
);
188 if (!NT_SUCCESS(Status
))
194 if (PathBuffer
!= NULL
)
195 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer
);
203 PWCHAR SourceFileName
,
204 PWCHAR DestinationFileName
)
206 OBJECT_ATTRIBUTES ObjectAttributes
;
207 HANDLE FileHandleSource
;
208 HANDLE FileHandleDest
;
209 static IO_STATUS_BLOCK IoStatusBlock
;
210 FILE_STANDARD_INFORMATION FileStandard
;
211 FILE_BASIC_INFORMATION FileBasic
;
213 UNICODE_STRING FileName
;
215 PVOID SourceFileMap
= 0;
216 HANDLE SourceFileSection
;
217 SIZE_T SourceSectionSize
= 0;
218 LARGE_INTEGER ByteOffset
;
221 RtlInitUnicodeString(&FileName
,
224 InitializeObjectAttributes(&ObjectAttributes
,
226 OBJ_CASE_INSENSITIVE
,
230 Status
= NtOpenFile(&FileHandleSource
,
235 FILE_SEQUENTIAL_ONLY
);
236 if (!NT_SUCCESS(Status
))
238 DPRINT1("NtOpenFile failed: %x, %wZ\n", Status
, &FileName
);
242 FileHandleSource
= CreateFileW(SourceFileName
,
249 if (FileHandleSource
== INVALID_HANDLE_VALUE
)
251 Status
= STATUS_UNSUCCESSFUL
;
256 Status
= NtQueryInformationFile(FileHandleSource
,
259 sizeof(FILE_STANDARD_INFORMATION
),
260 FileStandardInformation
);
261 if (!NT_SUCCESS(Status
))
263 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
267 Status
= NtQueryInformationFile(FileHandleSource
,
268 &IoStatusBlock
,&FileBasic
,
269 sizeof(FILE_BASIC_INFORMATION
),
270 FileBasicInformation
);
271 if (!NT_SUCCESS(Status
))
273 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
277 Status
= NtCreateSection(&SourceFileSection
,
284 if (!NT_SUCCESS(Status
))
286 DPRINT1("NtCreateSection failed: %x, %S\n", Status
, SourceFileName
);
290 Status
= NtMapViewOfSection(SourceFileSection
,
300 if (!NT_SUCCESS(Status
))
302 DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status
, SourceFileName
);
306 RtlInitUnicodeString(&FileName
,
307 DestinationFileName
);
309 InitializeObjectAttributes(&ObjectAttributes
,
311 OBJ_CASE_INSENSITIVE
,
315 Status
= NtCreateFile(&FileHandleDest
,
316 GENERIC_WRITE
| SYNCHRONIZE
,
320 FILE_ATTRIBUTE_NORMAL
,
323 FILE_NO_INTERMEDIATE_BUFFERING
|
324 FILE_SEQUENTIAL_ONLY
|
325 FILE_SYNCHRONOUS_IO_NONALERT
,
328 if (!NT_SUCCESS(Status
))
330 DPRINT1("NtCreateFile failed: %x\n", Status
);
334 RegionSize
= (ULONG
)PAGE_ROUND_UP(FileStandard
.EndOfFile
.u
.LowPart
);
335 IoStatusBlock
.Status
= 0;
336 ByteOffset
.QuadPart
= 0;
337 Status
= NtWriteFile(FileHandleDest
,
346 if (!NT_SUCCESS(Status
))
348 DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status
, IoStatusBlock
.Status
, &IoStatusBlock
, SourceFileMap
, RegionSize
);
352 /* Copy file date/time from source file */
353 Status
= NtSetInformationFile(FileHandleDest
,
356 sizeof(FILE_BASIC_INFORMATION
),
357 FileBasicInformation
);
358 if (!NT_SUCCESS(Status
))
360 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
364 /* shorten the file back to it's real size after completing the write */
365 Status
= NtSetInformationFile(FileHandleDest
,
367 &FileStandard
.EndOfFile
,
368 sizeof(FILE_END_OF_FILE_INFORMATION
),
369 FileEndOfFileInformation
);
370 if (!NT_SUCCESS(Status
))
372 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
376 NtClose(FileHandleDest
);
379 NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap
);
382 NtClose(SourceFileSection
);
385 NtClose(FileHandleSource
);
394 PWCHAR CabinetFileName
,
395 PWCHAR SourceFileName
,
396 PWCHAR DestinationPathName
)
400 DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
401 CabinetFileName
, SourceFileName
, DestinationPathName
);
403 if (HasCurrentCabinet
)
405 DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName
);
408 if ((HasCurrentCabinet
) && (wcscmp(CabinetFileName
, CurrentCabinetName
) == 0))
410 DPRINT("Using same cabinet as last time\n");
412 /* Use our last location because the files should be sequential */
413 CabStatus
= CabinetFindNextFileSequential(SourceFileName
, &Search
);
414 if (CabStatus
!= CAB_STATUS_SUCCESS
)
416 DPRINT("Sequential miss on file: %S\n", SourceFileName
);
418 /* Looks like we got unlucky */
419 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
424 DPRINT("Using new cabinet\n");
426 if (HasCurrentCabinet
)
431 wcscpy(CurrentCabinetName
, CabinetFileName
);
434 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
435 CabinetSetCabinetName(CabinetFileName
);
437 CabStatus
= CabinetOpen();
438 if (CabStatus
== CAB_STATUS_SUCCESS
)
440 DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
441 HasCurrentCabinet
= TRUE
;
445 DPRINT("Cannot open cabinet (%d)\n", CabStatus
);
446 return STATUS_UNSUCCESSFUL
;
449 /* We have to start at the beginning here */
450 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
453 if (CabStatus
!= CAB_STATUS_SUCCESS
)
455 DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName
, CabinetGetCabinetName());
456 return STATUS_UNSUCCESSFUL
;
459 CabinetSetDestinationPath(DestinationPathName
);
460 CabStatus
= CabinetExtractFile(&Search
);
461 if (CabStatus
!= CAB_STATUS_SUCCESS
)
463 DPRINT("Cannot extract file %S (%d)\n", SourceFileName
, CabStatus
);
464 return STATUS_UNSUCCESSFUL
;
467 return STATUS_SUCCESS
;
476 OBJECT_ATTRIBUTES ObjectAttributes
;
477 IO_STATUS_BLOCK IoStatusBlock
;
479 WCHAR FullName
[MAX_PATH
];
483 wcscpy(FullName
, PathName
);
484 if (FileName
!= NULL
)
486 if (FileName
[0] != L
'\\')
487 wcscat(FullName
, L
"\\");
488 wcscat(FullName
, FileName
);
491 RtlInitUnicodeString(&Name
,
494 InitializeObjectAttributes(&ObjectAttributes
,
496 OBJ_CASE_INSENSITIVE
,
500 Status
= NtOpenFile(&FileHandle
,
501 GENERIC_READ
| SYNCHRONIZE
,
505 FILE_SYNCHRONOUS_IO_NONALERT
);
506 if (!NT_SUCCESS(Status
))