mirror of
https://github.com/reactos/reactos.git
synced 2024-12-28 01:55:19 +00:00
Rewrote usetup's file copy and cabinet extraction code to use memory mapped files
This increased performance and the code is cleaner Still needs a bit more cleaning up, but so far, looks good, needs some testing svn path=/trunk/; revision=15403
This commit is contained in:
parent
7403e34ca9
commit
5d4d912efd
3 changed files with 577 additions and 1610 deletions
File diff suppressed because it is too large
Load diff
|
@ -82,12 +82,13 @@ typedef struct _CFFOLDER
|
|||
|
||||
typedef struct _CFFILE
|
||||
{
|
||||
ULONG FileSize; // Uncompressed file size in bytes
|
||||
ULONG FileOffset; // Uncompressed offset of file in the folder
|
||||
WORD FileControlID; // File control ID (CAB_FILE_*)
|
||||
WORD FileDate; // File date stamp, as used by DOS
|
||||
WORD FileTime; // File time stamp, as used by DOS
|
||||
WORD Attributes; // File attributes (CAB_ATTRIB_*)
|
||||
ULONG FileSize; // Uncompressed file size in bytes
|
||||
ULONG FileOffset; // Uncompressed offset of file in the folder
|
||||
WORD FolderIndex; // Index number of the folder that contains this file
|
||||
WORD FileDate; // File date stamp, as used by DOS
|
||||
WORD FileTime; // File time stamp, as used by DOS
|
||||
WORD Attributes; // File attributes (CAB_ATTRIB_*)
|
||||
CHAR FileName[];
|
||||
/* After this is the NULL terminated filename */
|
||||
} CFFILE, *PCFFILE;
|
||||
|
||||
|
@ -102,50 +103,12 @@ typedef struct _CFDATA
|
|||
*/
|
||||
} CFDATA, *PCFDATA;
|
||||
|
||||
typedef struct _CFDATA_NODE
|
||||
{
|
||||
struct _CFDATA_NODE *Next;
|
||||
struct _CFDATA_NODE *Prev;
|
||||
ULONG ScratchFilePosition; // Absolute offset in scratch file
|
||||
ULONG AbsoluteOffset; // Absolute offset in cabinet
|
||||
ULONG UncompOffset; // Uncompressed offset in folder
|
||||
CFDATA Data;
|
||||
} CFDATA_NODE, *PCFDATA_NODE;
|
||||
|
||||
typedef struct _CFFOLDER_NODE
|
||||
{
|
||||
struct _CFFOLDER_NODE *Next;
|
||||
struct _CFFOLDER_NODE *Prev;
|
||||
ULONG UncompOffset; // File size accumulator
|
||||
ULONG AbsoluteOffset;
|
||||
ULONG TotalFolderSize; // Total size of folder in current disk
|
||||
PCFDATA_NODE DataListHead;
|
||||
PCFDATA_NODE DataListTail;
|
||||
ULONG Index;
|
||||
BOOL Commit; // TRUE if the folder should be committed
|
||||
BOOL Delete; // TRUE if marked for deletion
|
||||
CFFOLDER Folder;
|
||||
} CFFOLDER_NODE, *PCFFOLDER_NODE;
|
||||
|
||||
typedef struct _CFFILE_NODE
|
||||
{
|
||||
struct _CFFILE_NODE *Next;
|
||||
struct _CFFILE_NODE *Prev;
|
||||
CFFILE File;
|
||||
PWCHAR FileName;
|
||||
PCFDATA_NODE DataBlock; // First data block of file. NULL if not known
|
||||
BOOL Commit; // TRUE if the file data should be committed
|
||||
BOOL Delete; // TRUE if marked for deletion
|
||||
PCFFOLDER_NODE FolderNode; // Folder this file belong to
|
||||
} CFFILE_NODE, *PCFFILE_NODE;
|
||||
|
||||
|
||||
typedef struct _CAB_SEARCH
|
||||
{
|
||||
WCHAR Search[MAX_PATH]; // Search criteria
|
||||
PCFFILE_NODE Next; // Pointer to next node
|
||||
PCFFILE File; // Pointer to current CFFILE
|
||||
PWCHAR FileName; // Current filename
|
||||
WCHAR Search[MAX_PATH]; // Search criteria
|
||||
WCHAR Cabinet[MAX_PATH];
|
||||
USHORT Index;
|
||||
PCFFILE File; // Pointer to current CFFILE
|
||||
} CAB_SEARCH, *PCAB_SEARCH;
|
||||
|
||||
|
||||
|
@ -169,9 +132,9 @@ typedef struct _CAB_SEARCH
|
|||
|
||||
/* Uncompresses a data block */
|
||||
typedef ULONG (*PCABINET_CODEC_UNCOMPRESS)(PVOID OutputBuffer,
|
||||
PVOID InputBuffer,
|
||||
ULONG InputLength,
|
||||
PULONG OutputLength);
|
||||
PVOID InputBuffer,
|
||||
PLONG InputLength,
|
||||
PLONG OutputLength);
|
||||
|
||||
|
||||
/* Codec status codes */
|
||||
|
@ -232,7 +195,7 @@ ULONG CabinetFindFirst(PWCHAR FileName, PCAB_SEARCH Search);
|
|||
/* Locates the next file in the current cabinet file */
|
||||
ULONG CabinetFindNext(PCAB_SEARCH Search);
|
||||
/* Extracts a file from the current cabinet file */
|
||||
ULONG CabinetExtractFile(PWCHAR FileName);
|
||||
ULONG CabinetExtractFile(PCAB_SEARCH Search);
|
||||
/* Select codec engine to use */
|
||||
VOID CabinetSelectCodec(ULONG Id);
|
||||
/* Set event handlers */
|
||||
|
|
|
@ -107,11 +107,13 @@ SetupCopyFile(PWCHAR SourceFileName,
|
|||
IO_STATUS_BLOCK IoStatusBlock;
|
||||
FILE_STANDARD_INFORMATION FileStandard;
|
||||
FILE_BASIC_INFORMATION FileBasic;
|
||||
FILE_POSITION_INFORMATION FilePosition;
|
||||
PUCHAR Buffer;
|
||||
ULONG RegionSize;
|
||||
UNICODE_STRING FileName;
|
||||
NTSTATUS Status;
|
||||
PVOID SourceFileMap = 0;
|
||||
HANDLE SourceFileSection;
|
||||
ULONG SourceSectionSize = 0;
|
||||
|
||||
Buffer = NULL;
|
||||
|
||||
|
@ -130,9 +132,10 @@ SetupCopyFile(PWCHAR SourceFileName,
|
|||
&IoStatusBlock,
|
||||
FILE_SHARE_READ,
|
||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
return(Status);
|
||||
DPRINT1("NtOpenFile failed: %x\n", Status);
|
||||
goto done;
|
||||
}
|
||||
|
||||
Status = NtQueryInformationFile(FileHandleSource,
|
||||
|
@ -140,20 +143,48 @@ SetupCopyFile(PWCHAR SourceFileName,
|
|||
&FileStandard,
|
||||
sizeof(FILE_STANDARD_INFORMATION),
|
||||
FileStandardInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
return(Status);
|
||||
DPRINT1("NtQueryInformationFile failed: %x\n", Status);
|
||||
goto closesrc;
|
||||
}
|
||||
|
||||
Status = NtQueryInformationFile(FileHandleSource,
|
||||
&IoStatusBlock,&FileBasic,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
return(Status);
|
||||
DPRINT1("NtQueryInformationFile failed: %x\n", Status);
|
||||
goto closesrc;
|
||||
}
|
||||
|
||||
Status = NtCreateSection( &SourceFileSection,
|
||||
SECTION_MAP_READ,
|
||||
0,
|
||||
0,
|
||||
PAGE_READONLY,
|
||||
0,
|
||||
FileHandleSource);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtCreateSection failed: %x\n", Status);
|
||||
goto closesrc;
|
||||
}
|
||||
|
||||
Status = NtMapViewOfSection( SourceFileSection,
|
||||
NtCurrentProcess(),
|
||||
&SourceFileMap,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&SourceSectionSize,
|
||||
0,
|
||||
SEC_COMMIT,
|
||||
PAGE_READONLY );
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT1("NtMapViewOfSection failed: %x\n", Status);
|
||||
goto closesrcsec;
|
||||
}
|
||||
|
||||
RtlInitUnicodeString(&FileName,
|
||||
|
@ -176,121 +207,55 @@ SetupCopyFile(PWCHAR SourceFileName,
|
|||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
|
||||
NULL,
|
||||
0);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
FilePosition.CurrentByteOffset.QuadPart = 0;
|
||||
|
||||
Status = NtSetInformationFile(FileHandleSource,
|
||||
&IoStatusBlock,
|
||||
&FilePosition,
|
||||
sizeof(FILE_POSITION_INFORMATION),
|
||||
FilePositionInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
Status = NtSetInformationFile(FileHandleDest,
|
||||
&IoStatusBlock,
|
||||
&FilePosition,
|
||||
sizeof(FILE_POSITION_INFORMATION),
|
||||
FilePositionInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
return(Status);
|
||||
DPRINT1("NtCreateFile failed: %x\n", Status);
|
||||
goto unmapsrcsec;
|
||||
}
|
||||
|
||||
RegionSize = PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
|
||||
if (RegionSize > 0x100000)
|
||||
IoStatusBlock.Status = 0;
|
||||
Status = NtWriteFile(FileHandleDest,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
&IoStatusBlock,
|
||||
SourceFileMap,
|
||||
RegionSize,
|
||||
0,
|
||||
0);
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
RegionSize = 0x100000;
|
||||
DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize);
|
||||
goto closedest;
|
||||
}
|
||||
Status = NtAllocateVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&Buffer,
|
||||
2,
|
||||
&RegionSize,
|
||||
MEM_RESERVE | MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
while (TRUE)
|
||||
{
|
||||
Status = NtReadFile(FileHandleSource,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
Buffer,
|
||||
RegionSize,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&Buffer,
|
||||
&RegionSize,
|
||||
MEM_RELEASE);
|
||||
if (Status == STATUS_END_OF_FILE)
|
||||
{
|
||||
DPRINT("STATUS_END_OF_FILE\n");
|
||||
break;
|
||||
}
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
return(Status);
|
||||
}
|
||||
|
||||
DPRINT("Bytes read %lu\n", IoStatusBlock.Information);
|
||||
|
||||
Status = NtWriteFile(FileHandleDest,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&IoStatusBlock,
|
||||
Buffer,
|
||||
IoStatusBlock.Information,
|
||||
NULL,
|
||||
NULL);
|
||||
if (!NT_SUCCESS(Status))
|
||||
{
|
||||
NtFreeVirtualMemory(NtCurrentProcess(),
|
||||
(PVOID *)&Buffer,
|
||||
&RegionSize,
|
||||
MEM_RELEASE);
|
||||
NtClose(FileHandleSource);
|
||||
NtClose(FileHandleDest);
|
||||
return(Status);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Copy file date/time from source file */
|
||||
Status = NtSetInformationFile(FileHandleDest,
|
||||
&IoStatusBlock,
|
||||
&FileBasic,
|
||||
sizeof(FILE_BASIC_INFORMATION),
|
||||
FileBasicInformation);
|
||||
if (!NT_SUCCESS(Status))
|
||||
if(!NT_SUCCESS(Status))
|
||||
{
|
||||
DPRINT("NtSetInformationFile() failed (Status %lx)\n", Status);
|
||||
DPRINT1("NtSetInformationFile failed: %x\n", Status);
|
||||
goto closedest;
|
||||
}
|
||||
|
||||
NtClose(FileHandleSource);
|
||||
/* shorten the file back to it's real size after completing the write */
|
||||
NtSetInformationFile(FileHandleDest,
|
||||
&IoStatusBlock,
|
||||
&FileStandard.EndOfFile,
|
||||
sizeof(FILE_END_OF_FILE_INFORMATION),
|
||||
FileEndOfFileInformation);
|
||||
closedest:
|
||||
NtClose(FileHandleDest);
|
||||
|
||||
unmapsrcsec:
|
||||
NtUnmapViewOfSection( NtCurrentProcess(), SourceFileMap );
|
||||
closesrcsec:
|
||||
NtClose(SourceFileSection);
|
||||
closesrc:
|
||||
NtClose(FileHandleSource);
|
||||
done:
|
||||
return(Status);
|
||||
}
|
||||
|
||||
|
@ -301,6 +266,7 @@ SetupExtractFile(PWCHAR CabinetFileName,
|
|||
PWCHAR DestinationPathName)
|
||||
{
|
||||
ULONG CabStatus;
|
||||
CAB_SEARCH Search;
|
||||
|
||||
DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
|
||||
CabinetFileName, SourceFileName, DestinationPathName);
|
||||
|
@ -343,7 +309,8 @@ SetupExtractFile(PWCHAR CabinetFileName,
|
|||
}
|
||||
|
||||
CabinetSetDestinationPath(DestinationPathName);
|
||||
CabStatus = CabinetExtractFile(SourceFileName);
|
||||
CabinetFindFirst( SourceFileName, &Search );
|
||||
CabStatus = CabinetExtractFile(&Search);
|
||||
if (CabStatus != CAB_STATUS_SUCCESS)
|
||||
{
|
||||
DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
|
||||
|
|
Loading…
Reference in a new issue