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
;
41 SetupCreateDirectory(PWCHAR DirectoryName
)
43 OBJECT_ATTRIBUTES ObjectAttributes
;
44 IO_STATUS_BLOCK IoStatusBlock
;
45 UNICODE_STRING PathName
;
46 HANDLE DirectoryHandle
;
49 RtlCreateUnicodeString(&PathName
,
51 if (PathName
.Length
> sizeof(WCHAR
) &&
52 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 2] == L
'\\' &&
53 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 1] == L
'.')
55 PathName
.Length
-= sizeof(WCHAR
);
56 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
)] = 0;
59 if (PathName
.Length
> sizeof(WCHAR
) &&
60 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
) - 1] == L
'\\')
62 PathName
.Length
-= sizeof(WCHAR
);
63 PathName
.Buffer
[PathName
.Length
/ sizeof(WCHAR
)] = 0;
66 InitializeObjectAttributes(&ObjectAttributes
,
68 OBJ_CASE_INSENSITIVE
| OBJ_INHERIT
,
72 Status
= NtCreateFile(&DirectoryHandle
,
77 FILE_ATTRIBUTE_DIRECTORY
,
78 FILE_SHARE_READ
| FILE_SHARE_WRITE
,
83 if (NT_SUCCESS(Status
))
85 NtClose(DirectoryHandle
);
88 RtlFreeUnicodeString(&PathName
);
95 SetupCopyFile(PWCHAR SourceFileName
,
96 PWCHAR DestinationFileName
)
98 OBJECT_ATTRIBUTES ObjectAttributes
;
99 HANDLE FileHandleSource
;
100 HANDLE FileHandleDest
;
101 static IO_STATUS_BLOCK IoStatusBlock
;
102 FILE_STANDARD_INFORMATION FileStandard
;
103 FILE_BASIC_INFORMATION FileBasic
;
105 UNICODE_STRING FileName
;
107 PVOID SourceFileMap
= 0;
108 HANDLE SourceFileSection
;
109 SIZE_T SourceSectionSize
= 0;
110 LARGE_INTEGER ByteOffset
;
113 RtlInitUnicodeString(&FileName
,
116 InitializeObjectAttributes(&ObjectAttributes
,
118 OBJ_CASE_INSENSITIVE
,
122 Status
= NtOpenFile(&FileHandleSource
,
127 FILE_SEQUENTIAL_ONLY
);
128 if(!NT_SUCCESS(Status
))
130 DPRINT1("NtOpenFile failed: %x, %wZ\n", Status
, &FileName
);
134 FileHandleSource
= CreateFileW(SourceFileName
, GENERIC_READ
, FILE_SHARE_READ
, NULL
, OPEN_EXISTING
, 0, NULL
);
135 if (FileHandleSource
== INVALID_HANDLE_VALUE
)
137 Status
= STATUS_UNSUCCESSFUL
;
142 Status
= NtQueryInformationFile(FileHandleSource
,
145 sizeof(FILE_STANDARD_INFORMATION
),
146 FileStandardInformation
);
147 if(!NT_SUCCESS(Status
))
149 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
152 Status
= NtQueryInformationFile(FileHandleSource
,
153 &IoStatusBlock
,&FileBasic
,
154 sizeof(FILE_BASIC_INFORMATION
),
155 FileBasicInformation
);
156 if(!NT_SUCCESS(Status
))
158 DPRINT1("NtQueryInformationFile failed: %x\n", Status
);
162 Status
= NtCreateSection( &SourceFileSection
,
169 if(!NT_SUCCESS(Status
))
171 DPRINT1("NtCreateSection failed: %x, %wZ\n", Status
, SourceFileName
);
175 Status
= NtMapViewOfSection( SourceFileSection
,
185 if(!NT_SUCCESS(Status
))
187 DPRINT1("NtMapViewOfSection failed: %x, %wZ\n", Status
, SourceFileName
);
191 RtlInitUnicodeString(&FileName
,
192 DestinationFileName
);
194 InitializeObjectAttributes(&ObjectAttributes
,
196 OBJ_CASE_INSENSITIVE
,
200 Status
= NtCreateFile(&FileHandleDest
,
205 FILE_ATTRIBUTE_NORMAL
,
208 FILE_NO_INTERMEDIATE_BUFFERING
|
209 FILE_SEQUENTIAL_ONLY
|
210 FILE_SYNCHRONOUS_IO_NONALERT
,
213 if(!NT_SUCCESS(Status
))
215 DPRINT1("NtCreateFile failed: %x\n", Status
);
219 RegionSize
= (ULONG
)PAGE_ROUND_UP(FileStandard
.EndOfFile
.u
.LowPart
);
220 IoStatusBlock
.Status
= 0;
221 ByteOffset
.QuadPart
= 0;
222 Status
= NtWriteFile(FileHandleDest
,
231 if(!NT_SUCCESS(Status
))
233 DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status
, IoStatusBlock
.Status
, &IoStatusBlock
, SourceFileMap
, RegionSize
);
236 /* Copy file date/time from source file */
237 Status
= NtSetInformationFile(FileHandleDest
,
240 sizeof(FILE_BASIC_INFORMATION
),
241 FileBasicInformation
);
242 if(!NT_SUCCESS(Status
))
244 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
248 /* shorten the file back to it's real size after completing the write */
249 Status
= NtSetInformationFile(FileHandleDest
,
251 &FileStandard
.EndOfFile
,
252 sizeof(FILE_END_OF_FILE_INFORMATION
),
253 FileEndOfFileInformation
);
255 if(!NT_SUCCESS(Status
))
257 DPRINT1("NtSetInformationFile failed: %x\n", Status
);
261 NtClose(FileHandleDest
);
263 NtUnmapViewOfSection( NtCurrentProcess(), SourceFileMap
);
265 NtClose(SourceFileSection
);
267 NtClose(FileHandleSource
);
274 SetupExtractFile(PWCHAR CabinetFileName
,
275 PWCHAR SourceFileName
,
276 PWCHAR DestinationPathName
)
280 DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
281 CabinetFileName
, SourceFileName
, DestinationPathName
);
283 if (HasCurrentCabinet
)
285 DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName
);
288 if ((HasCurrentCabinet
) && (wcscmp(CabinetFileName
, CurrentCabinetName
) == 0))
290 DPRINT("Using same cabinet as last time\n");
292 /* Use our last location because the files should be sequential */
293 CabStatus
= CabinetFindNextFileSequential(SourceFileName
, &Search
);
294 if (CabStatus
!= CAB_STATUS_SUCCESS
)
296 DPRINT("Sequential miss on file: %S\n", SourceFileName
);
298 /* Looks like we got unlucky */
299 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
304 DPRINT("Using new cabinet\n");
306 if (HasCurrentCabinet
)
311 wcscpy(CurrentCabinetName
, CabinetFileName
);
314 CabinetSetEventHandlers(NULL
, NULL
, NULL
);
315 CabinetSetCabinetName(CabinetFileName
);
317 CabStatus
= CabinetOpen();
318 if (CabStatus
== CAB_STATUS_SUCCESS
)
320 DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
321 HasCurrentCabinet
= TRUE
;
325 DPRINT("Cannot open cabinet (%d)\n", CabStatus
);
326 return STATUS_UNSUCCESSFUL
;
329 /* We have to start at the beginning here */
330 CabStatus
= CabinetFindFirst(SourceFileName
, &Search
);
333 if (CabStatus
!= CAB_STATUS_SUCCESS
)
335 DPRINT1("Unable to find '%S' in cabinet '%S'\n", SourceFileName
, CabinetGetCabinetName());
336 return STATUS_UNSUCCESSFUL
;
339 CabinetSetDestinationPath(DestinationPathName
);
340 CabStatus
= CabinetExtractFile(&Search
);
341 if (CabStatus
!= CAB_STATUS_SUCCESS
)
343 DPRINT("Cannot extract file %S (%d)\n", SourceFileName
, CabStatus
);
344 return STATUS_UNSUCCESSFUL
;
347 return STATUS_SUCCESS
;
352 DoesFileExist(PWSTR PathName
,
355 OBJECT_ATTRIBUTES ObjectAttributes
;
356 IO_STATUS_BLOCK IoStatusBlock
;
358 WCHAR FullName
[MAX_PATH
];
362 wcscpy(FullName
, PathName
);
363 if (FileName
!= NULL
)
365 if (FileName
[0] != L
'\\')
366 wcscat(FullName
, L
"\\");
367 wcscat(FullName
, FileName
);
370 RtlInitUnicodeString(&Name
,
373 InitializeObjectAttributes(&ObjectAttributes
,
375 OBJ_CASE_INSENSITIVE
,
379 Status
= NtOpenFile(&FileHandle
,
384 FILE_SYNCHRONOUS_IO_NONALERT
);
385 if (!NT_SUCCESS(Status
))