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
))
140 // TODO: Add check for 8.3 too.
142 /* Check for whitespaces */
143 for (i
= 0; i
< Length
; i
++)
145 if (isspace(InstallDir
[i
]))
154 SetupCreateDirectory(
157 PWCHAR PathBuffer
= NULL
;
159 ULONG BackslashCount
;
161 NTSTATUS Status
= STATUS_SUCCESS
;
163 Size
= (wcslen(PathName
) + 1) * sizeof(WCHAR
);
164 PathBuffer
= RtlAllocateHeap(RtlGetProcessHeap(), HEAP_ZERO_MEMORY
, Size
);
165 if (PathBuffer
== NULL
)
166 return STATUS_INSUFFICIENT_RESOURCES
;
168 wcscpy(PathBuffer
, PathName
);
169 EndPtr
= PathBuffer
+ wcslen(PathName
);
173 /* Skip the '\Device\HarddiskX\PartitionY\ part */
175 while (Ptr
< EndPtr
&& BackslashCount
< 4)
189 DPRINT("PathBuffer: %S\n", PathBuffer
);
190 if (!DoesPathExist(PathBuffer
))
192 DPRINT("Create: %S\n", PathBuffer
);
193 Status
= SetupCreateSingleDirectory(PathBuffer
);
194 if (!NT_SUCCESS(Status
))
204 if (!DoesPathExist(PathBuffer
))
206 DPRINT("Create: %S\n", PathBuffer
);
207 Status
= SetupCreateSingleDirectory(PathBuffer
);
208 if (!NT_SUCCESS(Status
))
214 if (PathBuffer
!= NULL
)
215 RtlFreeHeap(RtlGetProcessHeap(), 0, PathBuffer
);
223 PWCHAR SourceFileName
,
224 PWCHAR DestinationFileName
)
226 OBJECT_ATTRIBUTES ObjectAttributes
;
227 HANDLE FileHandleSource
;
228 HANDLE FileHandleDest
;
229 static IO_STATUS_BLOCK IoStatusBlock
;
230 FILE_STANDARD_INFORMATION FileStandard
;
231 FILE_BASIC_INFORMATION FileBasic
;
233 UNICODE_STRING FileName
;
235 PVOID SourceFileMap
= 0;
236 HANDLE SourceFileSection
;
237 SIZE_T SourceSectionSize
= 0;
238 LARGE_INTEGER ByteOffset
;
241 RtlInitUnicodeString(&FileName
,
244 InitializeObjectAttributes(&ObjectAttributes
,
246 OBJ_CASE_INSENSITIVE
,
250 Status
= NtOpenFile(&FileHandleSource
,
255 FILE_SEQUENTIAL_ONLY
);
256 if (!NT_SUCCESS(Status
))
258 DPRINT1("NtOpenFile failed: %x, %wZ\n", Status
, &FileName
);
262 FileHandleSource
= CreateFileW(SourceFileName
,
269 if (FileHandleSource
== INVALID_HANDLE_VALUE
)
271 Status
= STATUS_UNSUCCESSFUL
;
276 Status
= NtQueryInformationFile(FileHandleSource
,
279 sizeof(FILE_STANDARD_INFORMATION
),
280 FileStandardInformation
);
281 if (!NT_SUCCESS(Status
))
283 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
287 Status
= NtQueryInformationFile(FileHandleSource
,
288 &IoStatusBlock
,&FileBasic
,
289 sizeof(FILE_BASIC_INFORMATION
),
290 FileBasicInformation
);
291 if (!NT_SUCCESS(Status
))
293 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
297 Status
= NtCreateSection(&SourceFileSection
,
304 if (!NT_SUCCESS(Status
))
306 DPRINT1("NtCreateSection failed: %x, %S\n", Status
, SourceFileName
);
310 Status
= NtMapViewOfSection(SourceFileSection
,
320 if (!NT_SUCCESS(Status
))
322 DPRINT1("NtMapViewOfSection failed: %x, %S\n", Status
, SourceFileName
);
326 RtlInitUnicodeString(&FileName
,
327 DestinationFileName
);
329 InitializeObjectAttributes(&ObjectAttributes
,
331 OBJ_CASE_INSENSITIVE
,
335 Status
= NtCreateFile(&FileHandleDest
,
336 GENERIC_WRITE
| SYNCHRONIZE
,
340 FILE_ATTRIBUTE_NORMAL
,
343 FILE_NO_INTERMEDIATE_BUFFERING
|
344 FILE_SEQUENTIAL_ONLY
|
345 FILE_SYNCHRONOUS_IO_NONALERT
,
348 if (!NT_SUCCESS(Status
))
350 DPRINT1("NtCreateFile failed: %x, %wZ\n", Status
, &FileName
);
354 RegionSize
= (ULONG
)PAGE_ROUND_UP(FileStandard
.EndOfFile
.u
.LowPart
);
355 IoStatusBlock
.Status
= 0;
356 ByteOffset
.QuadPart
= 0;
357 Status
= NtWriteFile(FileHandleDest
,
366 if (!NT_SUCCESS(Status
))
368 DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status
, IoStatusBlock
.Status
, &IoStatusBlock
, SourceFileMap
, RegionSize
);
372 /* Copy file date/time from source file */
373 Status
= NtSetInformationFile(FileHandleDest
,
376 sizeof(FILE_BASIC_INFORMATION
),
377 FileBasicInformation
);
378 if (!NT_SUCCESS(Status
))
380 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
384 /* shorten the file back to it's real size after completing the write */
385 Status
= NtSetInformationFile(FileHandleDest
,
387 &FileStandard
.EndOfFile
,
388 sizeof(FILE_END_OF_FILE_INFORMATION
),
389 FileEndOfFileInformation
);
390 if (!NT_SUCCESS(Status
))
392 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
396 NtClose(FileHandleDest
);
399 NtUnmapViewOfSection(NtCurrentProcess(), SourceFileMap
);
402 NtClose(SourceFileSection
);
405 NtClose(FileHandleSource
);
414 PWCHAR CabinetFileName
,
415 PWCHAR SourceFileName
,
416 PWCHAR DestinationPathName
)
420 DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
421 CabinetFileName
, SourceFileName
, DestinationPathName
);
423 if (HasCurrentCabinet
)
425 DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName
);
428 if ((HasCurrentCabinet
) && (wcscmp(CabinetFileName
, CurrentCabinetName
) == 0))
430 DPRINT("Using same cabinet as last time\n");
432 /* Use our last location because the files should be sequential */
433 CabStatus
= CabinetFindNextFileSequential(SourceFileName
, &Search
);
434 if (CabStatus
!= CAB_STATUS_SUCCESS
)
436 DPRINT("Sequential miss on file: %S\n", SourceFileName
);
438 /* Looks like we got unlucky */
439 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
444 DPRINT("Using new cabinet\n");
446 if (HasCurrentCabinet
)
451 wcscpy(CurrentCabinetName
, CabinetFileName
);
454 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
455 CabinetSetCabinetName(CabinetFileName
);
457 CabStatus
= CabinetOpen();
458 if (CabStatus
== CAB_STATUS_SUCCESS
)
460 DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
461 HasCurrentCabinet
= TRUE
;
465 DPRINT("Cannot open cabinet (%d)\n", CabStatus
);
466 return STATUS_UNSUCCESSFUL
;
469 /* We have to start at the beginning here */
470 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
473 if (CabStatus
!= CAB_STATUS_SUCCESS
)
475 DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName
, CabinetGetCabinetName());
476 return STATUS_UNSUCCESSFUL
;
479 CabinetSetDestinationPath(DestinationPathName
);
480 CabStatus
= CabinetExtractFile(&Search
);
481 if (CabStatus
!= CAB_STATUS_SUCCESS
)
483 DPRINT("Cannot extract file %S (%d)\n", SourceFileName
, CabStatus
);
484 return STATUS_UNSUCCESSFUL
;
487 return STATUS_SUCCESS
;
496 OBJECT_ATTRIBUTES ObjectAttributes
;
497 IO_STATUS_BLOCK IoStatusBlock
;
499 WCHAR FullName
[MAX_PATH
];
503 wcscpy(FullName
, PathName
);
504 if (FileName
!= NULL
)
506 if (FileName
[0] != L
'\\')
507 wcscat(FullName
, L
"\\");
508 wcscat(FullName
, FileName
);
511 RtlInitUnicodeString(&Name
,
514 InitializeObjectAttributes(&ObjectAttributes
,
516 OBJ_CASE_INSENSITIVE
,
520 Status
= NtOpenFile(&FileHandle
,
521 GENERIC_READ
| SYNCHRONIZE
,
525 FILE_SYNCHRONOUS_IO_NONALERT
);
526 if (!NT_SUCCESS(Status
))