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:
Phillip Susi 2005-05-19 00:59:40 +00:00
parent 7403e34ca9
commit 5d4d912efd
3 changed files with 577 additions and 1610 deletions

File diff suppressed because it is too large Load diff

View file

@ -84,10 +84,11 @@ 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 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
WCHAR Cabinet[MAX_PATH];
USHORT Index;
PCFFILE File; // Pointer to current CFFILE
PWCHAR FileName; // Current filename
} CAB_SEARCH, *PCAB_SEARCH;
@ -170,8 +133,8 @@ typedef struct _CAB_SEARCH
/* Uncompresses a data block */
typedef ULONG (*PCABINET_CODEC_UNCOMPRESS)(PVOID OutputBuffer,
PVOID InputBuffer,
ULONG InputLength,
PULONG OutputLength);
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 */

View file

@ -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)
{
RegionSize = 0x100000;
}
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);
IoStatusBlock.Status = 0;
Status = NtWriteFile(FileHandleDest,
NULL,
NULL,
NULL,
0,
0,
0,
&IoStatusBlock,
Buffer,
IoStatusBlock.Information,
NULL,
NULL);
if (!NT_SUCCESS(Status))
SourceFileMap,
RegionSize,
0,
0);
if(!NT_SUCCESS(Status))
{
NtFreeVirtualMemory(NtCurrentProcess(),
(PVOID *)&Buffer,
&RegionSize,
MEM_RELEASE);
NtClose(FileHandleSource);
NtClose(FileHandleDest);
return(Status);
DPRINT1("NtWriteFile failed: %x:%x, iosb: %p src: %p, size: %x\n", Status, IoStatusBlock.Status, &IoStatusBlock, SourceFileMap, RegionSize);
goto closedest;
}
}
/* 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);