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 Modified: trunk/reactos/subsys/system/usetup/cabinet.c Modified: trunk/reactos/subsys/system/usetup/cabinet.h Modified: trunk/reactos/subsys/system/usetup/filesup.c _____
Modified: trunk/reactos/subsys/system/usetup/cabinet.c --- trunk/reactos/subsys/system/usetup/cabinet.c 2005-05-18 22:05:11 UTC (rev 15402) +++ trunk/reactos/subsys/system/usetup/cabinet.c 2005-05-19 00:59:40 UTC (rev 15403) @@ -46,30 +46,21 @@
static WCHAR DiskNext[256]; // Label of cabinet in file CabinetNext static ULONG FolderUncompSize = 0; // Uncompressed size of folder static ULONG BytesLeftInBlock = 0; // Number of bytes left in current block -static BOOL ReuseBlock = FALSE; static WCHAR DestPath[MAX_PATH]; static HANDLE FileHandle; +static HANDLE FileSectionHandle; +static PUCHAR FileBuffer; +static ULONG DestFileSize; +static ULONG FileSize; static BOOL FileOpen = FALSE; -static CFHEADER CABHeader; +static PCFHEADER PCABHeader; +static PCFFOLDER CabinetFolders; static ULONG CabinetReserved = 0; static ULONG FolderReserved = 0; static ULONG DataReserved = 0; -static PCFFOLDER_NODE FolderListHead = NULL; -static PCFFOLDER_NODE FolderListTail = NULL; -static PCFFOLDER_NODE CurrentFolderNode = NULL; -static PCFDATA_NODE CurrentDataNode = NULL; -static PCFFILE_NODE FileListHead = NULL; -static PCFFILE_NODE FileListTail = NULL; static ULONG CodecId; static PCABINET_CODEC_UNCOMPRESS CodecUncompress = NULL; static BOOL CodecSelected = FALSE; -static PVOID InputBuffer = NULL; -static PVOID CurrentIBuffer = NULL; // Current offset in input buffer -static ULONG CurrentIBufferSize = 0; // Bytes left in input buffer -static PVOID OutputBuffer = NULL; -static PVOID CurrentOBuffer = NULL; // Current offset in output buffer -static ULONG CurrentOBufferSize = 0; // Bytes left in output buffer -static BOOL RestartSearch = FALSE; static ULONG LastFileOffset = 0; // Uncompressed offset of last extracted file static PCABINET_OVERWRITE OverwriteHandler = NULL; static PCABINET_EXTRACT ExtractHandler = NULL; @@ -94,20 +85,23 @@
ULONG RawCodecUncompress(PVOID OutputBuffer, - PVOID InputBuffer, - ULONG InputLength, - PULONG OutputLength) + PVOID InputBuffer, + PLONG InputLength, + PLONG OutputLength) /* * FUNCTION: Uncompresses data in a buffer * ARGUMENTS: * OutputBuffer = Pointer to buffer to place uncompressed data * InputBuffer = Pointer to buffer with data to be uncompressed - * InputLength = Length of input buffer - * OutputLength = Address of buffer to place size of uncompressed data + * InputLength = Length of input buffer before, and amount consumed after + * Negative to indicate that this is not the start of a new block + * OutputLength = Length of output buffer before, amount filled after + * Negative to indicate that this is not the end of the block */ { - memcpy(OutputBuffer, InputBuffer, InputLength); - *OutputLength = InputLength; + LONG In = abs(*InputLength), Out = abs(*OutputLength); + memcpy(OutputBuffer, InputBuffer, In < Out ? In : Out); + *InputLength = *OutputLength = In < Out ? In : Out; return CS_SUCCESS; }
@@ -116,70 +110,80 @@
ULONG MSZipCodecUncompress(PVOID OutputBuffer, - PVOID InputBuffer, - ULONG InputLength, - PULONG OutputLength) + PVOID InputBuffer, + PLONG InputLength, + PLONG OutputLength) /* * FUNCTION: Uncompresses data in a buffer * ARGUMENTS: * OutputBuffer = Pointer to buffer to place uncompressed data * InputBuffer = Pointer to buffer with data to be uncompressed - * InputLength = Length of input buffer - * OutputLength = Address of buffer to place size of uncompressed data + * InputLength = Length of input buffer before, and amount consumed after + * Negative to indicate that this is not the start of a new block + * OutputLength = Length of output buffer before, amount filled after + * Negative to indicate that this is not the end of the block */ { USHORT Magic; INT Status;
- DPRINT("InputLength (%d).\n", InputLength); + DPRINT("MSZipCodecUncompress( OutputBuffer = %x, InputBuffer = %x, InputLength = %d, OutputLength = %d.\n", OutputBuffer, InputBuffer, *InputLength, *OutputLength); + if( *InputLength > 0 ) + { + Magic = *((PUSHORT)InputBuffer);
- Magic = *((PUSHORT)InputBuffer); + if (Magic != MSZIP_MAGIC) + { + DPRINT("Bad MSZIP block header magic (0x%X)\n", Magic); + return CS_BADSTREAM; + } + + ZStream.next_in = (PUCHAR)((ULONG)InputBuffer + 2); + ZStream.avail_in = *InputLength - 2; + ZStream.next_out = (PUCHAR)OutputBuffer; + ZStream.avail_out = abs(*OutputLength);
- if (Magic != MSZIP_MAGIC) - { - DPRINT("Bad MSZIP block header magic (0x%X)\n", Magic); - return CS_BADSTREAM; - } + /* WindowBits is passed < 0 to tell that there is no zlib header. + * Note that in this case inflate *requires* an extra "dummy" byte + * after the compressed stream in order to complete decompression and + * return Z_STREAM_END. + */ + Status = inflateInit2(&ZStream, -MAX_WBITS); + if (Status != Z_OK) + { + DPRINT("inflateInit2() returned (%d).\n", Status); + return CS_BADSTREAM; + } + ZStream.total_in = 2; + } + else { + ZStream.avail_in = -*InputLength; + ZStream.next_in = (PUCHAR)InputBuffer; + ZStream.next_out = (PUCHAR)OutputBuffer; + ZStream.avail_out = abs(*OutputLength); + ZStream.total_in = 0; + } + ZStream.total_out = 0; + Status = inflate(&ZStream, Z_SYNC_FLUSH ); + if (Status != Z_OK && Status != Z_STREAM_END) + { + DPRINT("inflate() returned (%d) (%s).\n", Status, ZStream.msg); + if (Status == Z_MEM_ERROR) + return CS_NOMEMORY; + return CS_BADSTREAM; + }
- ZStream.next_in = (PUCHAR)((ULONG)InputBuffer + 2); - ZStream.avail_in = InputLength - 2; - ZStream.next_out = (PUCHAR)OutputBuffer; - ZStream.avail_out = CAB_BLOCKSIZE + 12; - - /* WindowBits is passed < 0 to tell that there is no zlib header. - * Note that in this case inflate *requires* an extra "dummy" byte - * after the compressed stream in order to complete decompression and - * return Z_STREAM_END. - */ - Status = inflateInit2(&ZStream, -MAX_WBITS); - if (Status != Z_OK) - { - DPRINT("inflateInit2() returned (%d).\n", Status); - return CS_BADSTREAM; - } - - while ((ZStream.total_out < CAB_BLOCKSIZE + 12) && - (ZStream.total_in < InputLength - 2)) - { - Status = inflate(&ZStream, Z_NO_FLUSH); - if (Status == Z_STREAM_END) break; - if (Status != Z_OK) - { - DPRINT("inflate() returned (%d) (%s).\n", Status, ZStream.msg); - if (Status == Z_MEM_ERROR) - return CS_NOMEMORY; - return CS_BADSTREAM; - } - } - + if( *OutputLength > 0 ) + { + Status = inflateEnd(&ZStream); + if (Status != Z_OK) + { + DPRINT("inflateEnd() returned (%d).\n", Status); + return CS_BADSTREAM; + } + } *OutputLength = ZStream.total_out; - - Status = inflateEnd(&ZStream); - if (Status != Z_OK) - { - DPRINT("inflateEnd() returned (%d).\n", Status); - return CS_BADSTREAM; - } + *InputLength = ZStream.total_in; return CS_SUCCESS; }
@@ -197,97 +201,14 @@ RtlFreeHeap(ProcessHeap, 0, address); }
- -static DWORD -SeekInFile(HANDLE hFile, - LONG lDistanceToMove, - PLONG lpDistanceToMoveHigh, - DWORD dwMoveMethod, - PNTSTATUS Status) -{ - FILE_POSITION_INFORMATION FilePosition; - FILE_STANDARD_INFORMATION FileStandard; - NTSTATUS errCode; - IO_STATUS_BLOCK IoStatusBlock; - LARGE_INTEGER Distance; - - DPRINT("SeekInFile(hFile %x, lDistanceToMove %d, dwMoveMethod %d)\n", - hFile,lDistanceToMove,dwMoveMethod); - - Distance.u.LowPart = lDistanceToMove; - if (lpDistanceToMoveHigh) - { - Distance.u.HighPart = *lpDistanceToMoveHigh; - } - else if (lDistanceToMove >= 0) - { - Distance.u.HighPart = 0; - } - else - { - Distance.u.HighPart = -1; - } - - if (dwMoveMethod == SEEK_CURRENT) - { - NtQueryInformationFile(hFile, - &IoStatusBlock, - &FilePosition, - sizeof(FILE_POSITION_INFORMATION), - FilePositionInformation); - FilePosition.CurrentByteOffset.QuadPart += Distance.QuadPart; - } - else if (dwMoveMethod == SEEK_END) - { - NtQueryInformationFile(hFile, - &IoStatusBlock, - &FileStandard, - sizeof(FILE_STANDARD_INFORMATION), - FileStandardInformation); - FilePosition.CurrentByteOffset.QuadPart = - FileStandard.EndOfFile.QuadPart + Distance.QuadPart; - } - else if ( dwMoveMethod == SEEK_BEGIN ) - { - FilePosition.CurrentByteOffset.QuadPart = Distance.QuadPart; - } - -// DPRINT1("GOTO FILE OFFSET: %I64d\n", FilePosition.CurrentByteOffset.QuadPart); - - errCode = NtSetInformationFile(hFile, - &IoStatusBlock, - &FilePosition, - sizeof(FILE_POSITION_INFORMATION), - FilePositionInformation); - if (!NT_SUCCESS(errCode)) - { - if (Status != NULL) - { - *Status = errCode; - } - return -1; - } - - if (lpDistanceToMoveHigh != NULL) - { - *lpDistanceToMoveHigh = FilePosition.CurrentByteOffset.u.HighPart; - } - if (Status != NULL) - { - *Status = STATUS_SUCCESS; - } - return FilePosition.CurrentByteOffset.u.LowPart; -} - - static BOOL ConvertSystemTimeToFileTime( - CONST SYSTEMTIME * lpSystemTime, + CONST SYSTEMTIME * lpSystemTime, LPFILETIME lpFileTime) { TIME_FIELDS TimeFields; LARGE_INTEGER liTime; - + TimeFields.Year = lpSystemTime->wYear; TimeFields.Month = lpSystemTime->wMonth; TimeFields.Day = lpSystemTime->wDay; @@ -295,7 +216,7 @@ TimeFields.Minute = lpSystemTime->wMinute; TimeFields.Second = lpSystemTime->wSecond; TimeFields.Milliseconds = lpSystemTime->wMilliseconds; - + if (RtlTimeFieldsToTime(&TimeFields, &liTime)) { lpFileTime->dwLowDateTime = liTime.u.LowPart; @@ -315,21 +236,21 @@ PDOSTIME pdtime = (PDOSTIME) &wFatTime; PDOSDATE pddate = (PDOSDATE) &wFatDate; SYSTEMTIME SystemTime; - + if (lpFileTime == NULL) return FALSE; - + SystemTime.wMilliseconds = 0; SystemTime.wSecond = pdtime->Second; SystemTime.wMinute = pdtime->Minute; SystemTime.wHour = pdtime->Hour; - + SystemTime.wDay = pddate->Day; SystemTime.wMonth = pddate->Month; SystemTime.wYear = 1980 + pddate->Year; - + ConvertSystemTimeToFileTime(&SystemTime,lpFileTime); - + return TRUE; }
@@ -345,9 +266,9 @@ */ { ULONG i, j; - + j = i = 0; - + while (Path [i++]) { if (Path[i - 1] == L'\') j = i; @@ -366,10 +287,10 @@ { PWCHAR FileName; DWORD i; - + i = 0; FileName = GetFileName(Path + i); - + if ((FileName != (Path + i)) && (FileName [-1] == L'\')) FileName--; if ((FileName == (Path + i)) && (FileName [0] == L'\')) @@ -379,7 +300,7 @@
static BOOL -SetAttributesOnFile(PCFFILE_NODE File, HANDLE hFile) +SetAttributesOnFile(PCFFILE File, HANDLE hFile) /* * FUNCTION: Sets attributes on a file * ARGUMENTS: @@ -393,19 +314,19 @@ NTSTATUS NtStatus; ULONG Attributes = 0;
- if (File->File.Attributes & CAB_ATTRIB_READONLY) + if (File->Attributes & CAB_ATTRIB_READONLY) Attributes |= FILE_ATTRIBUTE_READONLY;
- if (File->File.Attributes & CAB_ATTRIB_HIDDEN) + if (File->Attributes & CAB_ATTRIB_HIDDEN) Attributes |= FILE_ATTRIBUTE_HIDDEN;
- if (File->File.Attributes & CAB_ATTRIB_SYSTEM) + if (File->Attributes & CAB_ATTRIB_SYSTEM) Attributes |= FILE_ATTRIBUTE_SYSTEM;
- if (File->File.Attributes & CAB_ATTRIB_DIRECTORY) + if (File->Attributes & CAB_ATTRIB_DIRECTORY) Attributes |= FILE_ATTRIBUTE_DIRECTORY;
- if (File->File.Attributes & CAB_ATTRIB_ARCHIVE) + if (File->Attributes & CAB_ATTRIB_ARCHIVE) Attributes |= FILE_ATTRIBUTE_ARCHIVE;
NtStatus = NtQueryInformationFile(hFile, @@ -435,698 +356,7 @@ return NT_SUCCESS(NtStatus); }
- static ULONG -ReadBlock(PVOID Buffer, - ULONG Size, - PULONG BytesRead) -/* - * FUNCTION: Read a block of data from file - * ARGUMENTS: - * Buffer = Pointer to data buffer - * Size = Length of data buffer - * BytesRead = Pointer to ULONG that on return will contain - * number of bytes read - * RETURNS: - * Status of operation - */ -{ - IO_STATUS_BLOCK IoStatusBlock; - NTSTATUS NtStatus; - - NtStatus = NtReadFile(FileHandle, - NULL, - NULL, - NULL, - &IoStatusBlock, - Buffer, - Size, - NULL, - NULL); - if (!NT_SUCCESS(NtStatus)) - { - DPRINT("ReadBlock for %d bytes failed (%x)\n", Size, NtStatus); - *BytesRead = 0; - return CAB_STATUS_INVALID_CAB; - } - *BytesRead = Size; - return CAB_STATUS_SUCCESS; -} - - -static PCFFOLDER_NODE -NewFolderNode() -/* - * FUNCTION: Creates a new folder node - * RETURNS: - * Pointer to node if there was enough free memory available, otherwise NULL - */ -{ - PCFFOLDER_NODE Node; - - Node = (PCFFOLDER_NODE)RtlAllocateHeap (ProcessHeap, 0, sizeof(CFFOLDER_NODE)); - if (!Node) - return NULL; - - RtlZeroMemory(Node, sizeof(CFFOLDER_NODE)); - - Node->Folder.CompressionType = CAB_COMP_NONE; - - Node->Prev = FolderListTail; - - if (FolderListTail != NULL) - { - FolderListTail->Next = Node; - } - else - { - FolderListHead = Node; - } - FolderListTail = Node; - - return Node; -} - - -static PCFFILE_NODE -NewFileNode() -/* - * FUNCTION: Creates a new file node - * ARGUMENTS: - * FolderNode = Pointer to folder node to bind file to - * RETURNS: - * Pointer to node if there was enough free memory available, otherwise NULL - */ -{ - PCFFILE_NODE Node; - - Node = (PCFFILE_NODE)RtlAllocateHeap (ProcessHeap, 0, sizeof(CFFILE_NODE)); - if (!Node) - return NULL; - - RtlZeroMemory(Node, sizeof(CFFILE_NODE)); - - Node->Prev = FileListTail; - - if (FileListTail != NULL) - { - FileListTail->Next = Node; - } - else - { - FileListHead = Node; - } - FileListTail = Node; - - return Node; -} - - -static PCFDATA_NODE -NewDataNode(PCFFOLDER_NODE FolderNode) -/* - * FUNCTION: Creates a new data block node - * ARGUMENTS: - * FolderNode = Pointer to folder node to bind data block to - * RETURNS: - * Pointer to node if there was enough free memory available, otherwise NULL - */ -{ - PCFDATA_NODE Node; - - Node = (PCFDATA_NODE)RtlAllocateHeap (ProcessHeap, 0, sizeof(CFDATA_NODE)); - if (!Node) - return NULL; - - RtlZeroMemory(Node, sizeof(CFDATA_NODE)); - - Node->Prev = FolderNode->DataListTail; - - if (FolderNode->DataListTail != NULL) - { - FolderNode->DataListTail->Next = Node; - } - else - { - FolderNode->DataListHead = Node; - } - FolderNode->DataListTail = Node; - - return Node; -} - - -static VOID -DestroyDataNodes(PCFFOLDER_NODE FolderNode) -/* - * FUNCTION: Destroys data block nodes bound to a folder node - * ARGUMENTS: - * FolderNode = Pointer to folder node - */ -{ - PCFDATA_NODE PrevNode; - PCFDATA_NODE NextNode; - - NextNode = FolderNode->DataListHead; - while (NextNode != NULL) - { - PrevNode = NextNode->Next; - RtlFreeHeap(ProcessHeap, 0, NextNode); - NextNode = PrevNode; - } - FolderNode->DataListHead = NULL; - FolderNode->DataListTail = NULL; -} - - -static VOID -DestroyFileNodes() -/* - * FUNCTION: Destroys file nodes - * ARGUMENTS: - * FolderNode = Pointer to folder node - */ -{ - PCFFILE_NODE PrevNode; - PCFFILE_NODE NextNode; - - NextNode = FileListHead; - while (NextNode != NULL) - { - PrevNode = NextNode->Next; - if (NextNode->FileName) - RtlFreeHeap(ProcessHeap, 0, NextNode->FileName); - RtlFreeHeap(ProcessHeap, 0, NextNode); - NextNode = PrevNode; - } - FileListHead = NULL; - FileListTail = NULL; -} - - -#if 0 -static VOID -DestroyDeletedFileNodes() -/* - * FUNCTION: Destroys file nodes that are marked for deletion - */ -{ - PCFFILE_NODE CurNode; - PCFFILE_NODE NextNode; - - CurNode = FileListHead; - while (CurNode != NULL) - { - NextNode = CurNode->Next; - - if (CurNode->Delete) - { - if (CurNode->Prev != NULL) - { - CurNode->Prev->Next = CurNode->Next; - } - else - { - FileListHead = CurNode->Next; - if (FileListHead) - FileListHead->Prev = NULL; - } - - if (CurNode->Next != NULL) - { - CurNode->Next->Prev = CurNode->Prev; - } - else - { - FileListTail = CurNode->Prev; - if (FileListTail) - FileListTail->Next = NULL; - } - - DPRINT("Deleting file: '%S'\n", CurNode->FileName); - - if (CurNode->FileName) - RtlFreeHeap(ProcessHeap, 0, CurNode->FileName); - RtlFreeHeap(ProcessHeap, 0, CurNode); - } - CurNode = NextNode; - } -} -#endif - -static VOID -DestroyFolderNodes() -/* - * FUNCTION: Destroys folder nodes - */ -{ - PCFFOLDER_NODE PrevNode; - PCFFOLDER_NODE NextNode; - - NextNode = FolderListHead; - while (NextNode != NULL) - { - PrevNode = NextNode->Next; - DestroyDataNodes(NextNode); - RtlFreeHeap(ProcessHeap, 0, NextNode); - NextNode = PrevNode; - } - FolderListHead = NULL; - FolderListTail = NULL; -} - -#if 0 -static VOID -DestroyDeletedFolderNodes() -/* - * FUNCTION: Destroys folder nodes that are marked for deletion - */ -{ - PCFFOLDER_NODE CurNode; - PCFFOLDER_NODE NextNode; - - CurNode = FolderListHead; - while (CurNode != NULL) - { - NextNode = CurNode->Next; - - if (CurNode->Delete) - { - if (CurNode->Prev != NULL) - { - CurNode->Prev->Next = CurNode->Next; - } - else - { - FolderListHead = CurNode->Next; - if (FolderListHead) - FolderListHead->Prev = NULL; - } - - if (CurNode->Next != NULL) - { - CurNode->Next->Prev = CurNode->Prev; - } - else - { - FolderListTail = CurNode->Prev; - if (FolderListTail) - FolderListTail->Next = NULL; - } - - DestroyDataNodes(CurNode); - RtlFreeHeap(ProcessHeap, 0, CurNode); - } - CurNode = NextNode; - } -} -#endif - -static PCFFOLDER_NODE -LocateFolderNode(ULONG Index) -/* - * FUNCTION: Locates a folder node - * ARGUMENTS: - * Index = Folder index - * RETURNS: - * Pointer to folder node or NULL if the folder node was not found - */ -{ - PCFFOLDER_NODE Node; - - switch (Index) - { - case CAB_FILE_SPLIT: - return FolderListTail; - - case CAB_FILE_CONTINUED: - case CAB_FILE_PREV_NEXT: - return FolderListHead; - } - - Node = FolderListHead; - while (Node != NULL) - { - if (Node->Index == Index) - return Node; - Node = Node->Next; - } - return NULL; -} - - -static ULONG -GetAbsoluteOffset(PCFFILE_NODE File) -/* - * FUNCTION: Returns the absolute offset of a file - * ARGUMENTS: - * File = Pointer to CFFILE_NODE structure for file - * RETURNS: - * Status of operation - */ -{ - PCFDATA_NODE Node; - - DPRINT("FileName '%S' FileOffset (0x%X) FileSize (%d).\n", - (PWCHAR)File->FileName, - (UINT)File->File.FileOffset, - (UINT)File->File.FileSize); - - Node = CurrentFolderNode->DataListHead; - while (Node != NULL) - { - DPRINT("GetAbsoluteOffset(): Comparing (0x%X, 0x%X) (%d).\n", - (UINT)Node->UncompOffset, - (UINT)Node->UncompOffset + Node->Data.UncompSize, - (UINT)Node->Data.UncompSize); - - /* Node->Data.UncompSize will be 0 if the block is split - (ie. it is the last block in this cabinet) */ - if ((Node->Data.UncompSize == 0) || - ((File->File.FileOffset >= Node->UncompOffset) && - (File->File.FileOffset < Node->UncompOffset + - Node->Data.UncompSize))) - { - File->DataBlock = Node; - return CAB_STATUS_SUCCESS; - } - - Node = Node->Next; - } - return CAB_STATUS_INVALID_CAB; -} - - -static ULONG -LocateFile(PWCHAR FileName, - PCFFILE_NODE *File) -/* - * FUNCTION: Locates a file in the cabinet - * ARGUMENTS: - * FileName = Pointer to string with name of file to locate - * File = Address of pointer to CFFILE_NODE structure to fill - * RETURNS: - * Status of operation - * NOTES: - * Current folder is set to the folder of the file - */ -{ - PCFFILE_NODE Node; - ULONG Status; - - DPRINT("FileName '%S'\n", FileName); - - Node = FileListHead; - while (Node != NULL) - { - if (_wcsicmp(FileName, Node->FileName) == 0) - { - CurrentFolderNode = LocateFolderNode(Node->File.FileControlID); - if (!CurrentFolderNode) - { - DPRINT("Folder with index number (%d) not found.\n", - (UINT)Node->File.FileControlID); - return CAB_STATUS_INVALID_CAB; - } - - if (Node->DataBlock == NULL) - { - Status = GetAbsoluteOffset(Node); - } - else - Status = CAB_STATUS_SUCCESS; - *File = Node; - return Status; - } - Node = Node->Next; - } - return CAB_STATUS_NOFILE; -} - - -static ULONG -ReadString(PWCHAR String, ULONG MaxLength) -/* - * FUNCTION: Reads a NULL-terminated string from the cabinet - * ARGUMENTS: - * String = Pointer to buffer to place string - * MaxLength = Maximum length of string - * RETURNS: - * Status of operation - */ -{ - NTSTATUS NtStatus; - ULONG BytesRead; - ULONG Offset; - ULONG Status; - ULONG Size; - BOOL Found; - CHAR buf[MAX_PATH]; - ANSI_STRING as; - UNICODE_STRING us; - - Offset = 0; - Found = FALSE; - do - { - Size = ((Offset + 32) <= MaxLength)? 32 : MaxLength - Offset; - - if (Size == 0) - { - DPRINT("Too long a filename.\n"); - return CAB_STATUS_INVALID_CAB; - } - - Status = ReadBlock((PCFDATA)&buf[Offset], Size, &BytesRead); - if ((Status != CAB_STATUS_SUCCESS) || (BytesRead != Size)) - { - DPRINT("Cannot read from file (%d).\n", (UINT)Status); - return CAB_STATUS_INVALID_CAB; - } - - for (Size = Offset; Size < Offset + BytesRead; Size++) - { - if (buf[Size] == '\0') - { - Found = TRUE; - break; - } - } - - Offset += BytesRead; - } while (!Found); - - /* Back up some bytes */ - Size = (BytesRead - Size) - 1; - SeekInFile(FileHandle, -(LONG)Size, NULL, SEEK_CURRENT, &NtStatus); - if (!NT_SUCCESS(NtStatus)) - { - DPRINT("SeekInFile() failed (%x).\n", NtStatus); - return CAB_STATUS_INVALID_CAB; - } - - RtlInitAnsiString(&as, buf); - us.Buffer = String; - us.MaximumLength = MaxLength * sizeof(WCHAR); - us.Length = 0; - - RtlAnsiStringToUnicodeString(&us, &as, FALSE); - - return CAB_STATUS_SUCCESS; -} - - -static ULONG -ReadFileTable(VOID) -/* - * FUNCTION: Reads the file table from the cabinet file - * RETURNS: - * Status of operation - */ -{ - ULONG i; - ULONG Status; - ULONG BytesRead; - PCFFILE_NODE File; - NTSTATUS NtStatus; - - DPRINT("Reading file table at absolute offset (0x%X).\n", - CABHeader.FileTableOffset); - - /* Seek to file table */ - SeekInFile(FileHandle, CABHeader.FileTableOffset, NULL, SEEK_BEGIN, &NtStatus); - if (!NT_SUCCESS(NtStatus)) - { - DPRINT("SeekInFile() failed (%x).\n", NtStatus); - return CAB_STATUS_INVALID_CAB; - } - - for (i = 0; i < CABHeader.FileCount; i++) - { - File = NewFileNode(); - if (!File) - { - DPRINT("Insufficient memory.\n"); - return CAB_STATUS_NOMEMORY; - } - - if ((Status = ReadBlock(&File->File, sizeof(CFFILE), - &BytesRead)) != CAB_STATUS_SUCCESS) { - DPRINT("Cannot read from file (%d).\n", (UINT)Status); - return CAB_STATUS_INVALID_CAB; - } - - File->FileName = (PWCHAR)RtlAllocateHeap(ProcessHeap, 0, MAX_PATH * sizeof(WCHAR)); - if (!File->FileName) - { - DPRINT("Insufficient memory.\n"); - return CAB_STATUS_NOMEMORY; - } - - /* Read file name */ - Status = ReadString(File->FileName, MAX_PATH); - if (Status != CAB_STATUS_SUCCESS) - return Status; - - DPRINT("Found file '%S' at uncompressed offset (0x%X). Size (%d bytes) ControlId (0x%X).\n", - (PWCHAR)File->FileName, - (UINT)File->File.FileOffset, - (UINT)File->File.FileSize, - (UINT)File->File.FileControlID); - } - return CAB_STATUS_SUCCESS; -} - - -static ULONG -ReadDataBlocks(PCFFOLDER_NODE FolderNode) -/* - * FUNCTION: Reads all CFDATA blocks for a folder from the cabinet file - * ARGUMENTS: - * FolderNode = Pointer to CFFOLDER_NODE structure for folder - * RETURNS: - * Status of operation - */ -{ - ULONG AbsoluteOffset; - ULONG UncompOffset; - PCFDATA_NODE Node; - NTSTATUS NtStatus; - ULONG BytesRead; - ULONG Status; - ULONG i; - - DPRINT("Reading data blocks for folder (%d) at absolute offset (0x%X).\n", - FolderNode->Index, FolderNode->Folder.DataOffset); - - AbsoluteOffset = FolderNode->Folder.DataOffset; - UncompOffset = FolderNode->UncompOffset; - - for (i = 0; i < FolderNode->Folder.DataBlockCount; i++) - { - Node = NewDataNode(FolderNode); - if (!Node) - { - DPRINT("Insufficient memory.\n"); - return CAB_STATUS_NOMEMORY; - } - - /* Seek to data block */ - SeekInFile(FileHandle, AbsoluteOffset, NULL, SEEK_BEGIN, &NtStatus); [truncated at 1000 lines; 1631 more skipped]