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: base/setup/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 if(!RtlCreateUnicodeString(&PathName
, DirectoryName
))
52 return STATUS_NO_MEMORY
;
54 if (PathName
.Length
> sizeof(WCHAR
) &&
55 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 2] == L
'\\' &&
56 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 1] == L
'.')
58 PathName
.Length
-= sizeof(WCHAR
);
59 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
)] = 0;
62 if (PathName
.Length
> sizeof(WCHAR
) &&
63 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 1] == L
'\\')
65 PathName
.Length
-= sizeof(WCHAR
);
66 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
)] = 0;
69 InitializeObjectAttributes(&ObjectAttributes
,
71 OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
,
75 Status
= NtCreateFile(&DirectoryHandle
,
80 FILE_ATTRIBUTE_DIRECTORY
,
81 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
86 if (NT_SUCCESS(Status
))
88 NtClose(DirectoryHandle
);
91 RtlFreeUnicodeString(&PathName
);
102 OBJECT_ATTRIBUTES ObjectAttributes
;
103 IO_STATUS_BLOCK IoStatusBlock
;
108 RtlInitUnicodeString(&Name
,
111 InitializeObjectAttributes(&ObjectAttributes
,
113 OBJ_CASE_INSENSITIVE
,
117 Status
= NtOpenFile(&FileHandle
,
118 GENERIC_READ
| SYNCHRONIZE
,
122 FILE_SYNCHRONOUS_IO_NONALERT
);
123 if (!NT_SUCCESS(Status
))
141 // TODO: Add check for 8.3 too.
143 /* Check for whitespaces */
144 for (i
= 0; i
< Length
; i
++)
146 if (isspace(InstallDir
[i
]))
155 SetupCreateDirectory(
158 PWCHAR PathBuffer
= NULL
;
160 ULONG BackslashCount
;
162 NTSTATUS Status
= STATUS_SUCCESS
;
164 Size
= (wcslen(PathName
) + 1) * sizeof(WCHAR
);
165 PathBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
166 if (PathBuffer
== NULL
)
167 return STATUS_INSUFFICIENT_RESOURCES
;
169 wcscpy(PathBuffer
, PathName
);
170 EndPtr
= PathBuffer
+ wcslen(PathName
);
174 /* Skip the '\Device\HarddiskX\PartitionY\ part */
176 while (Ptr
< EndPtr
&& BackslashCount
< 4)
190 DPRINT("PathBuffer: %S\n", PathBuffer
);
191 if (!DoesPathExist(PathBuffer
))
193 DPRINT("Create: %S\n", PathBuffer
);
194 Status
= SetupCreateSingleDirectory(PathBuffer
);
195 if (!NT_SUCCESS(Status
))
205 if (!DoesPathExist(PathBuffer
))
207 DPRINT("Create: %S\n", PathBuffer
);
208 Status
= SetupCreateSingleDirectory(PathBuffer
);
209 if (!NT_SUCCESS(Status
))
215 if (PathBuffer
!= NULL
)
216 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer
);
224 PWCHAR SourceFileName
,
225 PWCHAR DestinationFileName
)
227 OBJECT_ATTRIBUTES ObjectAttributes
;
228 HANDLE FileHandleSource
;
229 HANDLE FileHandleDest
;
230 static IO_STATUS_BLOCK IoStatusBlock
;
231 FILE_STANDARD_INFORMATION FileStandard
;
232 FILE_BASIC_INFORMATION FileBasic
;
234 UNICODE_STRING FileName
;
236 PVOID SourceFileMap
= 0;
237 HANDLE SourceFileSection
;
238 SIZE_T SourceSectionSize
= 0;
239 LARGE_INTEGER ByteOffset
;
242 RtlInitUnicodeString(&FileName
,
245 InitializeObjectAttributes(&ObjectAttributes
,
247 OBJ_CASE_INSENSITIVE
,
251 Status
= NtOpenFile(&FileHandleSource
,
256 FILE_SEQUENTIAL_ONLY
);
257 if (!NT_SUCCESS(Status
))
259 DPRINT1("NtOpenFile failed: %x, %wZ\n", Status
, &FileName
);
263 FileHandleSource
= CreateFileW(SourceFileName
,
270 if (FileHandleSource
== INVALID_HANDLE_VALUE
)
272 Status
= STATUS_UNSUCCESSFUL
;
277 Status
= NtQueryInformationFile(FileHandleSource
,
280 sizeof(FILE_STANDARD_INFORMATION
),
281 FileStandardInformation
);
282 if (!NT_SUCCESS(Status
))
284 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
288 Status
= NtQueryInformationFile(FileHandleSource
,
289 &IoStatusBlock
,&FileBasic
,
290 sizeof(FILE_BASIC_INFORMATION
),
291 FileBasicInformation
);
292 if (!NT_SUCCESS(Status
))
294 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
298 Status
= NtCreateSection(&SourceFileSection
,
305 if (!NT_SUCCESS(Status
))
307 DPRINT1("NtCreateSection failed: %x, %S\n", Status
, SourceFileName
);
311 Status
= NtMapViewOfSection(SourceFileSection
,
321 if (!NT_SUCCESS(Status
))
323 DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status
, SourceFileName
);
327 RtlInitUnicodeString(&FileName
,
328 DestinationFileName
);
330 InitializeObjectAttributes(&ObjectAttributes
,
332 OBJ_CASE_INSENSITIVE
,
336 Status
= NtCreateFile(&FileHandleDest
,
337 GENERIC_WRITE
| SYNCHRONIZE
,
341 FILE_ATTRIBUTE_NORMAL
,
344 FILE_NO_INTERMEDIATE_BUFFERING
|
345 FILE_SEQUENTIAL_ONLY
|
346 FILE_SYNCHRONOUS_IO_NONALERT
,
349 if (!NT_SUCCESS(Status
))
351 DPRINT1("NtCreateFile failed: %x, %wZ\n", Status
, &FileName
);
355 RegionSize
= (ULONG
)PAGE_ROUND_UP(FileStandard
.EndOfFile
.u
.LowPart
);
356 IoStatusBlock
.Status
= 0;
357 ByteOffset
.QuadPart
= 0ULL;
358 Status
= NtWriteFile(FileHandleDest
,
367 if (!NT_SUCCESS(Status
))
369 DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status
, IoStatusBlock
.Status
, &IoStatusBlock
, SourceFileMap
, RegionSize
);
373 /* Copy file date/time from source file */
374 Status
= NtSetInformationFile(FileHandleDest
,
377 sizeof(FILE_BASIC_INFORMATION
),
378 FileBasicInformation
);
379 if (!NT_SUCCESS(Status
))
381 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
385 /* shorten the file back to it's real size after completing the write */
386 Status
= NtSetInformationFile(FileHandleDest
,
388 &FileStandard
.EndOfFile
,
389 sizeof(FILE_END_OF_FILE_INFORMATION
),
390 FileEndOfFileInformation
);
391 if (!NT_SUCCESS(Status
))
393 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
397 NtClose(FileHandleDest
);
400 NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap
);
403 NtClose(SourceFileSection
);
406 NtClose(FileHandleSource
);
415 PWCHAR CabinetFileName
,
416 PWCHAR SourceFileName
,
417 PWCHAR DestinationPathName
)
421 DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
422 CabinetFileName
, SourceFileName
, DestinationPathName
);
424 if (HasCurrentCabinet
)
426 DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName
);
429 if ((HasCurrentCabinet
) && (wcscmp(CabinetFileName
, CurrentCabinetName
) == 0))
431 DPRINT("Using same cabinet as last time\n");
433 /* Use our last location because the files should be sequential */
434 CabStatus
= CabinetFindNextFileSequential(SourceFileName
, &Search
);
435 if (CabStatus
!= CAB_STATUS_SUCCESS
)
437 DPRINT("Sequential miss on file: %S\n", SourceFileName
);
439 /* Looks like we got unlucky */
440 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
445 DPRINT("Using new cabinet\n");
447 if (HasCurrentCabinet
)
452 wcscpy(CurrentCabinetName
, CabinetFileName
);
455 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
456 CabinetSetCabinetName(CabinetFileName
);
458 CabStatus
= CabinetOpen();
459 if (CabStatus
== CAB_STATUS_SUCCESS
)
461 DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
462 HasCurrentCabinet
= TRUE
;
466 DPRINT("Cannot open cabinet (%d)\n", CabStatus
);
467 return STATUS_UNSUCCESSFUL
;
470 /* We have to start at the beginning here */
471 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
474 if (CabStatus
!= CAB_STATUS_SUCCESS
)
476 DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName
, CabinetGetCabinetName());
477 return STATUS_UNSUCCESSFUL
;
480 CabinetSetDestinationPath(DestinationPathName
);
481 CabStatus
= CabinetExtractFile(&Search
);
482 if (CabStatus
!= CAB_STATUS_SUCCESS
)
484 DPRINT("Cannot extract file %S (%d)\n", SourceFileName
, CabStatus
);
485 return STATUS_UNSUCCESSFUL
;
488 return STATUS_SUCCESS
;
497 OBJECT_ATTRIBUTES ObjectAttributes
;
498 IO_STATUS_BLOCK IoStatusBlock
;
500 WCHAR FullName
[MAX_PATH
];
504 wcscpy(FullName
, PathName
);
505 if (FileName
!= NULL
)
507 if (FileName
[0] != L
'\\')
508 wcscat(FullName
, L
"\\");
509 wcscat(FullName
, FileName
);
512 RtlInitUnicodeString(&Name
,
515 InitializeObjectAttributes(&ObjectAttributes
,
517 OBJ_CASE_INSENSITIVE
,
521 Status
= NtOpenFile(&FileHandle
,
522 GENERIC_READ
| SYNCHRONIZE
,
526 FILE_SYNCHRONOUS_IO_NONALERT
);
527 if (!NT_SUCCESS(Status
))