--- 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]