⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 cabinet.c

📁 ReactOS是一些高手根据Windows XP的内核编写出的类XP。内核实现机理和API函数调用几乎相同。甚至可以兼容XP的程序。喜欢研究系统内核的人可以看一看。
💻 C
📖 第 1 页 / 共 3 页
字号:
/*
 * 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 + -