📄 cabinet.c
字号:
/*
* COPYRIGHT: See COPYING in the top level directory
* PROJECT: ReactOS text-mode setup
* FILE: subsys/system/usetup/cabinet.c
* PURPOSE: Cabinet routines
* PROGRAMMERS: Casper S. Hornstrup (chorns@users.sourceforge.net)
* REVISIONS:
* CSH 15/08-2003 Created
*/
#include "usetup.h"
#include <zlib.h>
#define NDEBUG
#include <debug.h>
#define SEEK_BEGIN 0
#define SEEK_CURRENT 1
#ifndef SEEK_END
#define SEEK_END 2
#endif
typedef struct __DOSTIME
{
WORD Second:5;
WORD Minute:6;
WORD Hour:5;
} DOSTIME, *PDOSTIME;
typedef struct __DOSDATE
{
WORD Day:5;
WORD Month:4;
WORD Year:5;
} DOSDATE, *PDOSDATE;
static WCHAR CabinetName[256]; // Filename of current cabinet
static WCHAR CabinetPrev[256]; // Filename of previous cabinet
static WCHAR DiskPrev[256]; // Label of cabinet in file CabinetPrev
static WCHAR CabinetNext[256]; // Filename of next cabinet
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 WCHAR DestPath[MAX_PATH];
static HANDLE FileHandle;
static HANDLE FileSectionHandle;
static PUCHAR FileBuffer;
static SIZE_T DestFileSize;
static SIZE_T FileSize;
static BOOL FileOpen = FALSE;
static PCFHEADER PCABHeader;
static PCFFOLDER CabinetFolders;
static ULONG CabinetReserved = 0;
static ULONG FolderReserved = 0;
static ULONG DataReserved = 0;
static ULONG CodecId;
static PCABINET_CODEC_UNCOMPRESS CodecUncompress = NULL;
static BOOL CodecSelected = FALSE;
static ULONG LastFileOffset = 0; // Uncompressed offset of last extracted file
static PCABINET_OVERWRITE OverwriteHandler = NULL;
static PCABINET_EXTRACT ExtractHandler = NULL;
static PCABINET_DISK_CHANGE DiskChangeHandler = NULL;
static z_stream ZStream;
static PVOID CabinetReservedArea = NULL;
/* Needed by zlib, but we don't want the dependency on msvcrt.dll */
/* round to 16 bytes + alloc at minimum 16 bytes */
#define ROUND_SIZE(size) (max(16, ROUND_UP(size, 16)))
void* __cdecl malloc(size_t _size)
{
size_t nSize = ROUND_SIZE(_size);
if (nSize<_size)
return NULL;
return RtlAllocateHeap(ProcessHeap, HEAP_ZERO_MEMORY, nSize);
}
void __cdecl free(void* _ptr)
{
RtlFreeHeap(ProcessHeap, 0, _ptr);
}
void* __cdecl calloc(size_t _nmemb, size_t _size)
{
return (void*)RtlAllocateHeap (ProcessHeap, HEAP_ZERO_MEMORY, _size);
}
/* RAW codec */
ULONG
RawCodecUncompress(PVOID OutputBuffer,
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 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
*/
{
LONG In = abs(*InputLength), Out = abs(*OutputLength);
memcpy(OutputBuffer, InputBuffer, In < Out ? In : Out);
*InputLength = *OutputLength = In < Out ? In : Out;
return CS_SUCCESS;
}
/* MSZIP codec */
ULONG
MSZipCodecUncompress(PVOID OutputBuffer,
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 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("MSZipCodecUncompress( OutputBuffer = %x, InputBuffer = %x, InputLength = %d, OutputLength = %d.\n", OutputBuffer, InputBuffer, *InputLength, *OutputLength);
if( *InputLength > 0 )
{
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);
/* 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;
}
if( *OutputLength > 0 )
{
Status = inflateEnd(&ZStream);
if (Status != Z_OK)
{
DPRINT("inflateEnd() returned (%d).\n", Status);
return CS_BADSTREAM;
}
}
*OutputLength = ZStream.total_out;
*InputLength = ZStream.total_in;
return CS_SUCCESS;
}
/* Memory functions */
voidpf MSZipAlloc(voidpf opaque, uInt items, uInt size)
{
return (voidpf)RtlAllocateHeap (ProcessHeap, 0, items * size);
}
void MSZipFree (voidpf opaque, voidpf address)
{
RtlFreeHeap(ProcessHeap, 0, address);
}
static BOOL
ConvertSystemTimeToFileTime(
CONST SYSTEMTIME * lpSystemTime,
LPFILETIME lpFileTime)
{
TIME_FIELDS TimeFields;
LARGE_INTEGER liTime;
TimeFields.Year = lpSystemTime->wYear;
TimeFields.Month = lpSystemTime->wMonth;
TimeFields.Day = lpSystemTime->wDay;
TimeFields.Hour = lpSystemTime->wHour;
TimeFields.Minute = lpSystemTime->wMinute;
TimeFields.Second = lpSystemTime->wSecond;
TimeFields.Milliseconds = lpSystemTime->wMilliseconds;
if (RtlTimeFieldsToTime(&TimeFields, &liTime))
{
lpFileTime->dwLowDateTime = liTime.u.LowPart;
lpFileTime->dwHighDateTime = liTime.u.HighPart;
return TRUE;
}
return FALSE;
}
static BOOL
ConvertDosDateTimeToFileTime(
WORD wFatDate,
WORD wFatTime,
LPFILETIME lpFileTime)
{
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;
}
static PWCHAR
GetFileName(PWCHAR Path)
/*
* FUNCTION: Returns a pointer to file name
* ARGUMENTS:
* Path = Pointer to string with pathname
* RETURNS:
* Pointer to filename
*/
{
ULONG i, j;
j = i = 0;
while (Path [i++])
{
if (Path[i - 1] == L'\\') j = i;
}
return Path + j;
}
static VOID
RemoveFileName(PWCHAR Path)
/*
* FUNCTION: Removes a file name from a path
* ARGUMENTS:
* Path = Pointer to string with path
*/
{
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'\\'))
FileName++;
FileName[0] = 0;
}
static BOOL
SetAttributesOnFile(PCFFILE File, HANDLE hFile)
/*
* FUNCTION: Sets attributes on a file
* ARGUMENTS:
* File = Pointer to CFFILE node for file
* RETURNS:
* Status of operation
*/
{
FILE_BASIC_INFORMATION FileBasic;
IO_STATUS_BLOCK IoStatusBlock;
NTSTATUS NtStatus;
ULONG Attributes = 0;
if (File->Attributes & CAB_ATTRIB_READONLY)
Attributes |= FILE_ATTRIBUTE_READONLY;
if (File->Attributes & CAB_ATTRIB_HIDDEN)
Attributes |= FILE_ATTRIBUTE_HIDDEN;
if (File->Attributes & CAB_ATTRIB_SYSTEM)
Attributes |= FILE_ATTRIBUTE_SYSTEM;
if (File->Attributes & CAB_ATTRIB_DIRECTORY)
Attributes |= FILE_ATTRIBUTE_DIRECTORY;
if (File->Attributes & CAB_ATTRIB_ARCHIVE)
Attributes |= FILE_ATTRIBUTE_ARCHIVE;
NtStatus = NtQueryInformationFile(hFile,
&IoStatusBlock,
&FileBasic,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (!NT_SUCCESS(NtStatus))
{
DPRINT("NtQueryInformationFile() failed (%x).\n", NtStatus);
}
else
{
FileBasic.FileAttributes = Attributes;
NtStatus = NtSetInformationFile(hFile,
&IoStatusBlock,
&FileBasic,
sizeof(FILE_BASIC_INFORMATION),
FileBasicInformation);
if (!NT_SUCCESS(NtStatus))
{
DPRINT("NtSetInformationFile() failed (%x).\n", NtStatus);
}
}
return NT_SUCCESS(NtStatus);
}
static ULONG
CloseCabinet(VOID)
/*
* FUNCTION: Closes the current cabinet
* RETURNS:
* Status of operation
*/
{
if (FileBuffer)
{
NtUnmapViewOfSection( NtCurrentProcess(), FileBuffer );
NtClose( FileSectionHandle );
NtClose( FileHandle );
FileBuffer = NULL;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -