mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 21:12:10 +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
|
typedef struct _CFFILE
|
||||||
{
|
{
|
||||||
ULONG FileSize; // Uncompressed file size in bytes
|
ULONG FileSize; // Uncompressed file size in bytes
|
||||||
ULONG FileOffset; // Uncompressed offset of file in the folder
|
ULONG FileOffset; // Uncompressed offset of file in the folder
|
||||||
WORD FileControlID; // File control ID (CAB_FILE_*)
|
WORD FolderIndex; // Index number of the folder that contains this file
|
||||||
WORD FileDate; // File date stamp, as used by DOS
|
WORD FileDate; // File date stamp, as used by DOS
|
||||||
WORD FileTime; // File time stamp, as used by DOS
|
WORD FileTime; // File time stamp, as used by DOS
|
||||||
WORD Attributes; // File attributes (CAB_ATTRIB_*)
|
WORD Attributes; // File attributes (CAB_ATTRIB_*)
|
||||||
|
CHAR FileName[];
|
||||||
/* After this is the NULL terminated filename */
|
/* After this is the NULL terminated filename */
|
||||||
} CFFILE, *PCFFILE;
|
} CFFILE, *PCFFILE;
|
||||||
|
|
||||||
|
@ -102,50 +103,12 @@ typedef struct _CFDATA
|
||||||
*/
|
*/
|
||||||
} CFDATA, *PCFDATA;
|
} 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
|
typedef struct _CAB_SEARCH
|
||||||
{
|
{
|
||||||
WCHAR Search[MAX_PATH]; // Search criteria
|
WCHAR Search[MAX_PATH]; // Search criteria
|
||||||
PCFFILE_NODE Next; // Pointer to next node
|
WCHAR Cabinet[MAX_PATH];
|
||||||
PCFFILE File; // Pointer to current CFFILE
|
USHORT Index;
|
||||||
PWCHAR FileName; // Current filename
|
PCFFILE File; // Pointer to current CFFILE
|
||||||
} CAB_SEARCH, *PCAB_SEARCH;
|
} CAB_SEARCH, *PCAB_SEARCH;
|
||||||
|
|
||||||
|
|
||||||
|
@ -169,9 +132,9 @@ typedef struct _CAB_SEARCH
|
||||||
|
|
||||||
/* Uncompresses a data block */
|
/* Uncompresses a data block */
|
||||||
typedef ULONG (*PCABINET_CODEC_UNCOMPRESS)(PVOID OutputBuffer,
|
typedef ULONG (*PCABINET_CODEC_UNCOMPRESS)(PVOID OutputBuffer,
|
||||||
PVOID InputBuffer,
|
PVOID InputBuffer,
|
||||||
ULONG InputLength,
|
PLONG InputLength,
|
||||||
PULONG OutputLength);
|
PLONG OutputLength);
|
||||||
|
|
||||||
|
|
||||||
/* Codec status codes */
|
/* Codec status codes */
|
||||||
|
@ -232,7 +195,7 @@ ULONG CabinetFindFirst(PWCHAR FileName, PCAB_SEARCH Search);
|
||||||
/* Locates the next file in the current cabinet file */
|
/* Locates the next file in the current cabinet file */
|
||||||
ULONG CabinetFindNext(PCAB_SEARCH Search);
|
ULONG CabinetFindNext(PCAB_SEARCH Search);
|
||||||
/* Extracts a file from the current cabinet file */
|
/* Extracts a file from the current cabinet file */
|
||||||
ULONG CabinetExtractFile(PWCHAR FileName);
|
ULONG CabinetExtractFile(PCAB_SEARCH Search);
|
||||||
/* Select codec engine to use */
|
/* Select codec engine to use */
|
||||||
VOID CabinetSelectCodec(ULONG Id);
|
VOID CabinetSelectCodec(ULONG Id);
|
||||||
/* Set event handlers */
|
/* Set event handlers */
|
||||||
|
|
|
@ -107,11 +107,13 @@ SetupCopyFile(PWCHAR SourceFileName,
|
||||||
IO_STATUS_BLOCK IoStatusBlock;
|
IO_STATUS_BLOCK IoStatusBlock;
|
||||||
FILE_STANDARD_INFORMATION FileStandard;
|
FILE_STANDARD_INFORMATION FileStandard;
|
||||||
FILE_BASIC_INFORMATION FileBasic;
|
FILE_BASIC_INFORMATION FileBasic;
|
||||||
FILE_POSITION_INFORMATION FilePosition;
|
|
||||||
PUCHAR Buffer;
|
PUCHAR Buffer;
|
||||||
ULONG RegionSize;
|
ULONG RegionSize;
|
||||||
UNICODE_STRING FileName;
|
UNICODE_STRING FileName;
|
||||||
NTSTATUS Status;
|
NTSTATUS Status;
|
||||||
|
PVOID SourceFileMap = 0;
|
||||||
|
HANDLE SourceFileSection;
|
||||||
|
ULONG SourceSectionSize = 0;
|
||||||
|
|
||||||
Buffer = NULL;
|
Buffer = NULL;
|
||||||
|
|
||||||
|
@ -130,9 +132,10 @@ SetupCopyFile(PWCHAR SourceFileName,
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
FILE_SHARE_READ,
|
FILE_SHARE_READ,
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY);
|
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,
|
Status = NtQueryInformationFile(FileHandleSource,
|
||||||
|
@ -140,20 +143,48 @@ SetupCopyFile(PWCHAR SourceFileName,
|
||||||
&FileStandard,
|
&FileStandard,
|
||||||
sizeof(FILE_STANDARD_INFORMATION),
|
sizeof(FILE_STANDARD_INFORMATION),
|
||||||
FileStandardInformation);
|
FileStandardInformation);
|
||||||
if (!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
NtClose(FileHandleSource);
|
DPRINT1("NtQueryInformationFile failed: %x\n", Status);
|
||||||
return(Status);
|
goto closesrc;
|
||||||
}
|
}
|
||||||
|
|
||||||
Status = NtQueryInformationFile(FileHandleSource,
|
Status = NtQueryInformationFile(FileHandleSource,
|
||||||
&IoStatusBlock,&FileBasic,
|
&IoStatusBlock,&FileBasic,
|
||||||
sizeof(FILE_BASIC_INFORMATION),
|
sizeof(FILE_BASIC_INFORMATION),
|
||||||
FileBasicInformation);
|
FileBasicInformation);
|
||||||
if (!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
NtClose(FileHandleSource);
|
DPRINT1("NtQueryInformationFile failed: %x\n", Status);
|
||||||
return(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,
|
RtlInitUnicodeString(&FileName,
|
||||||
|
@ -176,121 +207,55 @@ SetupCopyFile(PWCHAR SourceFileName,
|
||||||
FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
|
FILE_SYNCHRONOUS_IO_NONALERT | FILE_SEQUENTIAL_ONLY,
|
||||||
NULL,
|
NULL,
|
||||||
0);
|
0);
|
||||||
if (!NT_SUCCESS(Status))
|
if(!NT_SUCCESS(Status))
|
||||||
{
|
{
|
||||||
NtClose(FileHandleSource);
|
DPRINT1("NtCreateFile failed: %x\n", Status);
|
||||||
return(Status);
|
goto unmapsrcsec;
|
||||||
}
|
|
||||||
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
RegionSize = PAGE_ROUND_UP(FileStandard.EndOfFile.u.LowPart);
|
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 */
|
/* Copy file date/time from source file */
|
||||||
Status = NtSetInformationFile(FileHandleDest,
|
Status = NtSetInformationFile(FileHandleDest,
|
||||||
&IoStatusBlock,
|
&IoStatusBlock,
|
||||||
&FileBasic,
|
&FileBasic,
|
||||||
sizeof(FILE_BASIC_INFORMATION),
|
sizeof(FILE_BASIC_INFORMATION),
|
||||||
FileBasicInformation);
|
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);
|
NtClose(FileHandleDest);
|
||||||
|
unmapsrcsec:
|
||||||
|
NtUnmapViewOfSection( NtCurrentProcess(), SourceFileMap );
|
||||||
|
closesrcsec:
|
||||||
|
NtClose(SourceFileSection);
|
||||||
|
closesrc:
|
||||||
|
NtClose(FileHandleSource);
|
||||||
|
done:
|
||||||
return(Status);
|
return(Status);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -301,6 +266,7 @@ SetupExtractFile(PWCHAR CabinetFileName,
|
||||||
PWCHAR DestinationPathName)
|
PWCHAR DestinationPathName)
|
||||||
{
|
{
|
||||||
ULONG CabStatus;
|
ULONG CabStatus;
|
||||||
|
CAB_SEARCH Search;
|
||||||
|
|
||||||
DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
|
DPRINT("SetupExtractFile(CabinetFileName %S, SourceFileName %S, DestinationPathName %S)\n",
|
||||||
CabinetFileName, SourceFileName, DestinationPathName);
|
CabinetFileName, SourceFileName, DestinationPathName);
|
||||||
|
@ -343,7 +309,8 @@ SetupExtractFile(PWCHAR CabinetFileName,
|
||||||
}
|
}
|
||||||
|
|
||||||
CabinetSetDestinationPath(DestinationPathName);
|
CabinetSetDestinationPath(DestinationPathName);
|
||||||
CabStatus = CabinetExtractFile(SourceFileName);
|
CabinetFindFirst( SourceFileName, &Search );
|
||||||
|
CabStatus = CabinetExtractFile(&Search);
|
||||||
if (CabStatus != CAB_STATUS_SUCCESS)
|
if (CabStatus != CAB_STATUS_SUCCESS)
|
||||||
{
|
{
|
||||||
DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
|
DPRINT("Cannot extract file %S (%d)\n", SourceFileName, CabStatus);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue