update for HEAD-2003091401
[reactos.git] / subsys / system / usetup / filesup.c
1 /*
2  *  ReactOS kernel
3  *  Copyright (C) 2002 ReactOS Team
4  *
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.
9  *
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.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program; if not, write to the Free Software
17  *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
18  */
19 /* $Id$
20  * COPYRIGHT:       See COPYING in the top level directory
21  * PROJECT:         ReactOS text-mode setup
22  * FILE:            subsys/system/usetup/filesup.c
23  * PURPOSE:         File support functions
24  * PROGRAMMER:      Eric Kohl
25  *                  Casper S. Hornstrup (chorns@users.sourceforge.net)
26  */
27
28 /* INCLUDES *****************************************************************/
29
30 #include <ddk/ntddk.h>
31 #include <ntdll/rtl.h>
32
33 #include "usetup.h"
34 #include "filesup.h"
35 #include "cabinet.h"
36
37
38 /* FUNCTIONS ****************************************************************/
39
40
41 static BOOLEAN HasCurrentCabinet = FALSE;
42 static WCHAR CurrentCabinetName[MAX_PATH];
43
44 NTSTATUS
45 CreateDirectory(PWCHAR DirectoryName)
46 {
47   OBJECT_ATTRIBUTES ObjectAttributes;
48   IO_STATUS_BLOCK IoStatusBlock;
49   UNICODE_STRING PathName;
50   HANDLE DirectoryHandle;
51   NTSTATUS Status;
52
53   RtlCreateUnicodeString(&PathName,
54                          DirectoryName);
55
56   InitializeObjectAttributes(&ObjectAttributes,
57                              &PathName,
58                              OBJ_CASE_INSENSITIVE | OBJ_INHERIT,
59                              NULL,
60                              NULL);
61
62   Status = NtCreateFile(&DirectoryHandle,
63                         DIRECTORY_ALL_ACCESS,
64                         &ObjectAttributes,
65                         &IoStatusBlock,
66                         NULL,
67                         FILE_ATTRIBUTE_DIRECTORY,
68                         0,
69                         FILE_CREATE,
70                         FILE_DIRECTORY_FILE,
71                         NULL,
72                         0);
73   if (NT_SUCCESS(Status))
74     {
75       NtClose(DirectoryHandle);
76     }
77
78   RtlFreeUnicodeString(&PathName);
79
80   return(Status);
81 }
82
83
84 NTSTATUS
85 SetupCopyFile(PWCHAR SourceFileName,
86               PWCHAR DestinationFileName)
87 {
88   OBJECT_ATTRIBUTES ObjectAttributes;
89   HANDLE FileHandleSource;
90   HANDLE FileHandleDest;
91   IO_STATUS_BLOCK IoStatusBlock;
92   FILE_STANDARD_INFORMATION FileStandard;
93   FILE_BASIC_INFORMATION FileBasic;
94   FILE_POSITION_INFORMATION FilePosition;
95   PUCHAR Buffer;
96   ULONG RegionSize;
97   UNICODE_STRING FileName;
98   NTSTATUS Status;
99
100   Buffer = NULL;
101
102   RtlInitUnicodeString(&FileName,
103                        SourceFileName);
104
105   InitializeObjectAttributes(&ObjectAttributes,
106                              &FileName,
107                              OBJ_CASE_INSENSITIVE,
108                              NULL,
109                              NULL);
110
111   Status = NtOpenFile(&FileHandleSource,
112                       FILE_READ_ACCESS,
113                       &ObjectAttributes,
114                       &IoStatusBlock,
115                       FILE_SHARE_READ,
116                       FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY);
117   if (!NT_SUCCESS(Status))
118     {
119       return(Status);
120     }
121
122   Status = NtQueryInformationFile(FileHandleSource,
123                                   &IoStatusBlock,
124                                   &FileStandard,
125                                   sizeof(FILE_STANDARD_INFORMATION),
126                                   FileStandardInformation);
127   if (!NT_SUCCESS(Status))
128     {
129      NtClose(FileHandleSource);
130      return(Status);
131     }
132
133   Status = NtQueryInformationFile(FileHandleSource,
134                                   &IoStatusBlock,&FileBasic,
135                                   sizeof(FILE_BASIC_INFORMATION),
136                                   FileBasicInformation);
137   if (!NT_SUCCESS(Status))
138     {
139       NtClose(FileHandleSource);
140       return(Status);
141     }
142
143   RtlInitUnicodeString(&FileName,
144                        DestinationFileName);
145
146   InitializeObjectAttributes(&ObjectAttributes,
147                              &FileName,
148                              OBJ_CASE_INSENSITIVE,
149                              NULL,
150                              NULL);
151
152   Status = NtCreateFile(&FileHandleDest,
153                         FILE_WRITE_ACCESS,
154                         &ObjectAttributes,
155                         &IoStatusBlock,
156                         NULL,
157                         FILE_ATTRIBUTE_NORMAL,
158                         0,
159                         FILE_OVERWRITE_IF,
160                         FILE_SYNCHRONOUS_IO_ALERT | FILE_SEQUENTIAL_ONLY,
161                         NULL,
162                         0);
163   if (!NT_SUCCESS(Status))
164     {
165       NtClose(FileHandleSource);
166       return(Status);
167     }
168
169   FilePosition.CurrentByteOffset.QuadPart = 0;
170
171   Status = NtSetInformationFile(FileHandleSource,
172                                 &IoStatusBlock,
173                                 &FilePosition,
174                                 sizeof(FILE_POSITION_INFORMATION),
175                                 FilePositionInformation);
176   if (!NT_SUCCESS(Status))
177     {
178       NtClose(FileHandleSource);
179       NtClose(FileHandleDest);
180       return(Status);
181     }
182
183   Status = NtSetInformationFile(FileHandleDest,
184                                 &IoStatusBlock,
185                                 &FilePosition,
186                                 sizeof(FILE_POSITION_INFORMATION),
187                                 FilePositionInformation);
188   if (!NT_SUCCESS(Status))
189     {
190       NtClose(FileHandleSource);
191       NtClose(FileHandleDest);
192       return(Status);
193     }
194
195   RegionSize = PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
196   if (RegionSize > 0x100000)
197     {
198       RegionSize = 0x100000;
199     }
200   Status = NtAllocateVirtualMemory(NtCurrentProcess(),
201                                    (PVOID *)&Buffer,
202                                    2,
203                                    &RegionSize,
204                                    MEM_RESERVE | MEM_COMMIT,
205                                    PAGE_READWRITE);
206   if (!NT_SUCCESS(Status))
207     {
208       NtClose(FileHandleSource);
209       NtClose(FileHandleDest);
210       return(Status);
211     }
212
213   while (TRUE)
214     {
215       Status = NtReadFile(FileHandleSource,
216                           NULL,
217                           NULL,
218                           NULL,
219                           &IoStatusBlock,
220                           Buffer,
221                           RegionSize,
222                           NULL,
223                           NULL);
224       if (!NT_SUCCESS(Status))
225         {
226           NtFreeVirtualMemory(NtCurrentProcess(),
227                               (PVOID *)&Buffer,
228                               &RegionSize,
229                               MEM_RELEASE);
230           if (Status == STATUS_END_OF_FILE)
231             {
232               DPRINT("STATUS_END_OF_FILE\n");
233               break;
234             }
235           NtClose(FileHandleSource);
236           NtClose(FileHandleDest);
237           return(Status);
238         }
239
240       DPRINT("Bytes read %lu\n", IoStatusBlock.Information);
241
242       Status = NtWriteFile(FileHandleDest,
243                            NULL,
244                            NULL,
245                            NULL,
246                            &IoStatusBlock,
247                            Buffer,
248                            IoStatusBlock.Information,
249                            NULL,
250                            NULL);
251       if (!NT_SUCCESS(Status))
252         {
253           NtFreeVirtualMemory(NtCurrentProcess(),
254                               (PVOID *)&Buffer,
255                               &RegionSize,
256                               MEM_RELEASE);
257           NtClose(FileHandleSource);
258           NtClose(FileHandleDest);
259           return(Status);
260         }
261     }
262
263
264   /* Copy file date/time from source file */
265   Status = NtSetInformationFile(FileHandleDest,
266                                 &IoStatusBlock,
267                                 &FileBasic,
268                                 sizeof(FILE_BASIC_INFORMATION),
269                                 FileBasicInformation);
270   if (!NT_SUCCESS(Status))
271     {
272       DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
273     }
274
275   NtClose(FileHandleSource);
276   NtClose(FileHandleDest);
277
278   return(Status);
279 }
280
281
282 NTSTATUS
283 SetupExtractFile(PWCHAR CabinetFileName,
284         PWCHAR SourceFileName,
285               PWCHAR DestinationPathName)
286 {
287   ULONG CabStatus;
288
289   DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
290     CabinetFileName, SourceFileName, DestinationPathName);
291
292   if (HasCurrentCabinet)
293     {
294       DPRINT("CurrentCabinetName: %S\n", CurrentCabinetName);
295     }
296
297   if ((HasCurrentCabinet) && (wcscmp(CabinetFileName, CurrentCabinetName) == 0))
298     {
299       DPRINT("Using same cabinet as last time\n");
300     }
301   else
302     {
303       DPRINT("Using new cabinet\n");
304
305       if (HasCurrentCabinet)
306         {
307           CabinetCleanup();
308         }
309
310       wcscpy(CurrentCabinetName, CabinetFileName); 
311
312       CabinetInitialize();
313       CabinetSetEventHandlers(NULL, NULL, NULL);
314       CabinetSetCabinetName(CabinetFileName);
315
316       CabStatus = CabinetOpen();
317       if (CabStatus == CAB_STATUS_SUCCESS)
318         {
319           DPRINT("Opened cabinet %S\n", CabinetGetCabinetName());
320           HasCurrentCabinet = TRUE;
321         }
322       else
323         {
324           DPRINT("Cannot open cabinet (%d)\n", CabStatus);
325           return STATUS_UNSUCCESSFUL;
326         }
327     }
328
329   CabinetSetDestinationPath(DestinationPathName);
330   CabStatus = CabinetExtractFile(SourceFileName);
331   if (CabStatus != CAB_STATUS_SUCCESS)
332     {
333       DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
334       return STATUS_UNSUCCESSFUL;
335     }
336
337   return STATUS_SUCCESS;
338 }
339
340
341 BOOLEAN
342 DoesFileExist(PWSTR PathName,
343               PWSTR FileName)
344 {
345   OBJECT_ATTRIBUTES ObjectAttributes;
346   IO_STATUS_BLOCK IoStatusBlock;
347   UNICODE_STRING Name;
348   WCHAR FullName[MAX_PATH];
349   HANDLE FileHandle;
350   NTSTATUS Status;
351
352   wcscpy(FullName, PathName);
353   if (FileName != NULL)
354     {
355       if (FileName[0] != L'\\')
356         wcscat(FullName, L"\\");
357       wcscat(FullName, FileName);
358     }
359
360   RtlInitUnicodeString(&Name,
361                        FullName);
362
363   InitializeObjectAttributes(&ObjectAttributes,
364                              &Name,
365                              OBJ_CASE_INSENSITIVE,
366                              NULL,
367                              NULL);
368
369   Status = NtOpenFile(&FileHandle,
370                       FILE_READ_ACCESS,
371                       &ObjectAttributes,
372                       &IoStatusBlock,
373                       0,
374                       FILE_SYNCHRONOUS_IO_ALERT);
375   if (!NT_SUCCESS(Status))
376     {
377       return(FALSE);
378     }
379
380   NtClose(FileHandle);
381
382   return(TRUE);
383 }
384
385 /* EOF */