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

📄 cabinet.c

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


VOID
CabinetInitialize(VOID)
/*
 * FUNCTION: Initialize archiver
 */
{
  ZStream.zalloc = MSZipAlloc;
  ZStream.zfree  = MSZipFree;
  ZStream.opaque = (voidpf)0;

  FileOpen = FALSE;
  wcscpy(DestPath, L"");
  
  CodecId       = CAB_CODEC_RAW;
  CodecSelected = TRUE;
  
  FolderUncompSize = 0;
  BytesLeftInBlock = 0;
  CabinetReserved = 0;
  FolderReserved = 0;
  DataReserved = 0;
  CabinetReservedArea = NULL;
  LastFileOffset = 0;
}


VOID
CabinetCleanup(VOID)
/*
 * FUNCTION: Cleanup archiver
 */
{
  CabinetClose();
}


BOOL
CabinetNormalizePath(PWCHAR Path,
  ULONG Length)
/*
 * FUNCTION: Normalizes a path
 * ARGUMENTS:
 *     Path   = Pointer to string with pathname
 *     Length = Number of characters in Path
 * RETURNS:
 *     TRUE if there was enough room in Path, or FALSE
 */
{
  ULONG n;
  BOOL OK = TRUE;
  
  if ((n = wcslen(Path)) &&
    (Path[n - 1] != L'\\') &&
    (OK = ((n + 1) < Length)))
    {
      Path[n]     = L'\\';
      Path[n + 1] = 0;
    }
  return OK;
}


PWCHAR
CabinetGetCabinetName()
/*
 * FUNCTION: Returns pointer to cabinet file name
 * RETURNS:
 *     Pointer to string with name of cabinet
 */
{
  return CabinetName;
}


VOID
CabinetSetCabinetName(PWCHAR FileName)
/*
 * FUNCTION: Sets cabinet file name
 * ARGUMENTS:
 *     FileName = Pointer to string with name of cabinet
 */
{
  wcscpy(CabinetName, FileName);
}


VOID
CabinetSetDestinationPath(PWCHAR DestinationPath)
/*
 * FUNCTION: Sets destination path
 * ARGUMENTS:
 *    DestinationPath = Pointer to string with name of destination path
 */
{
  wcscpy(DestPath, DestinationPath);
  if (wcslen(DestPath) > 0)
    CabinetNormalizePath(DestPath, MAX_PATH);
}


PWCHAR
CabinetGetDestinationPath()
/*
 * FUNCTION: Returns destination path
 * RETURNS:
 *    Pointer to string with name of destination path
 */
{
  return DestPath;
}


ULONG
CabinetOpen(VOID)
/*
 * FUNCTION: Opens a cabinet file
 * RETURNS:
 *     Status of operation
 */
{
  PUCHAR Buffer;
  UNICODE_STRING ustring;
  ANSI_STRING astring;
  
  if (!FileOpen)
    {
      OBJECT_ATTRIBUTES ObjectAttributes;
      IO_STATUS_BLOCK IoStatusBlock;
      UNICODE_STRING FileName;
      NTSTATUS NtStatus;
      ULONG Size;
    
      RtlInitUnicodeString(&FileName,
        CabinetName);

      InitializeObjectAttributes(&ObjectAttributes,
        &FileName,
        OBJ_CASE_INSENSITIVE,
        NULL,
        NULL);

      NtStatus = NtOpenFile(&FileHandle,
							GENERIC_READ | SYNCHRONIZE,
							&ObjectAttributes,
							&IoStatusBlock,
							FILE_SHARE_READ,
							FILE_SYNCHRONOUS_IO_NONALERT);
      if (!NT_SUCCESS(NtStatus))
        {
          DPRINT("Cannot open file (%S) (%x).\n", CabinetName, NtStatus);
          return CAB_STATUS_CANNOT_OPEN;
        }
      FileOpen = TRUE;

	  NtStatus = NtCreateSection(&FileSectionHandle,
								 SECTION_ALL_ACCESS,
								 0,
								 0,
								 PAGE_READONLY,
								 SEC_COMMIT,
								 FileHandle);
      if(!NT_SUCCESS(NtStatus))
		{
		  DPRINT("NtCreateSection failed: %x\n", NtStatus);
		  return CAB_STATUS_NOMEMORY;
		}
	  FileBuffer = 0;
	  FileSize = 0;
	  NtStatus = NtMapViewOfSection(FileSectionHandle,
									NtCurrentProcess(),
									(PVOID *)&FileBuffer,
									0,
									0,
									0,
									&FileSize,
									ViewUnmap,
									0,
									PAGE_READONLY);
	  if(!NT_SUCCESS(NtStatus))
		{
		  DPRINT("NtMapViewOfSection failed: %x\n", NtStatus);
		  return CAB_STATUS_NOMEMORY;
		}
	  DPRINT( "Cabinet file %S opened and mapped to %x\n", CabinetName, FileBuffer );
	  PCABHeader = (PCFHEADER)FileBuffer;
    
      /* Check header */
      if(FileSize <= sizeof(CFHEADER) ||
		 PCABHeader->Signature != CAB_SIGNATURE ||
		 PCABHeader->Version != CAB_VERSION ||
		 PCABHeader->FolderCount == 0 ||
		 PCABHeader->FileCount == 0 ||
		 PCABHeader->FileTableOffset < sizeof(CFHEADER))
		{
		  CloseCabinet();
		  DPRINT("File has invalid header.\n");
		  return CAB_STATUS_INVALID_CAB;
		}
  
      Size = 0;
	  Buffer = (PUCHAR)(PCABHeader+1);  
      /* Read/skip any reserved bytes */
      if (PCABHeader->Flags & CAB_FLAG_RESERVE)
        {
		  CabinetReserved = *(PUSHORT)Buffer;
		  Buffer += 2;
          FolderReserved = *Buffer;
		  Buffer++;
          DataReserved = *Buffer;
		  Buffer++;
          if (CabinetReserved > 0)
            {
			  CabinetReservedArea = Buffer;
			  Buffer += CabinetReserved;
            }
        }
  
      if (PCABHeader->Flags & CAB_FLAG_HASPREV)
        {
          /* The previous cabinet file is in the same directory as the current */
          wcscpy(CabinetPrev, CabinetName);
          RemoveFileName(CabinetPrev);
          CabinetNormalizePath(CabinetPrev, 256);
		  RtlInitAnsiString( &astring, (LPSTR)Buffer );
		  ustring.Length = wcslen( CabinetPrev );
		  ustring.Buffer = CabinetPrev + ustring.Length;
		  ustring.MaximumLength = sizeof( CabinetPrev ) - ustring.Length;
		  RtlAnsiStringToUnicodeString( &ustring, &astring, FALSE );
		  Buffer += astring.Length + 1;

          /* Read label of prev disk */
		  RtlInitAnsiString( &astring, (LPSTR)Buffer );
		  ustring.Length = 0;
		  ustring.Buffer = DiskPrev;
		  ustring.MaximumLength = sizeof( DiskPrev );
		  RtlAnsiStringToUnicodeString( &ustring, &astring, FALSE );
		  Buffer += astring.Length + 1;
        }
      else
        {
          wcscpy(CabinetPrev, L"");
          wcscpy(DiskPrev, L"");
        }
    
      if (PCABHeader->Flags & CAB_FLAG_HASNEXT)
        {
          /* The next cabinet file is in the same directory as the previous */
          wcscpy(CabinetNext, CabinetName);
          RemoveFileName(CabinetNext);
          CabinetNormalizePath(CabinetNext, 256);
		  RtlInitAnsiString( &astring, (LPSTR)Buffer );
		  ustring.Length = wcslen( CabinetNext );
		  ustring.Buffer = CabinetNext + ustring.Length;
		  ustring.MaximumLength = sizeof( CabinetNext ) - ustring.Length;
		  RtlAnsiStringToUnicodeString( &ustring, &astring, FALSE );
		  Buffer += astring.Length + 1;

          /* Read label of next disk */
		  RtlInitAnsiString( &astring, (LPSTR)Buffer );
		  ustring.Length = 0;
		  ustring.Buffer = DiskNext;
		  ustring.MaximumLength = sizeof( DiskNext );
		  RtlAnsiStringToUnicodeString( &ustring, &astring, FALSE );
		  Buffer += astring.Length + 1;
        }
      else
        {
          wcscpy(CabinetNext, L"");
          wcscpy(DiskNext,    L"");
        }
	  CabinetFolders = (PCFFOLDER)Buffer;
    }
  DPRINT( "CabinetOpen returning SUCCESS\n" );
  return CAB_STATUS_SUCCESS;
}


VOID
CabinetClose(VOID)
/*
 * FUNCTION: Closes the cabinet file
 */
{
  if (FileOpen)
    {
      CloseCabinet();

      FileOpen = FALSE;
    }
}


ULONG
CabinetFindFirst(PWCHAR FileName,
				 PCAB_SEARCH Search)
/*
 * FUNCTION: Finds the first file in the cabinet that matches a search criteria
 * ARGUMENTS:
 *     FileName = Pointer to search criteria
 *     Search   = Pointer to search structure
 * RETURNS:
 *     Status of operation
 */
{
  DPRINT( "CabinetFindFirst( FileName = %S )\n", FileName );
  wcsncpy(Search->Search, FileName, MAX_PATH);
  wcsncpy(Search->Cabinet, CabinetName, MAX_PATH);
  Search->File = 0;
  return CabinetFindNext(Search);
}


ULONG
CabinetFindNext(PCAB_SEARCH Search)
/*
 * FUNCTION: Finds next file in the cabinet that matches a search criteria
 * ARGUMENTS:
 *     Search = Pointer to search structure
 * RETURNS:
 *     Status of operation
 */
{
  ULONG Status;
  PCFFILE Prev;
  ANSI_STRING AnsiString;
  UNICODE_STRING UnicodeString;
  WCHAR FileName[MAX_PATH];

  if( wcscmp( Search->Cabinet, CabinetName ) != 0 )
	Search->File = 0;    // restart search of cabinet has changed since last find
  if( !Search->File )
	{
	  // starting new search or cabinet
	  Search->File = (PCFFILE)(FileBuffer + PCABHeader->FileTableOffset);
	  Search->Index = 0;
	  Prev = 0;
	}
  else Prev = Search->File;
  while(1)
	{
	  // look at each file in the archive and see if we found a match
	  if( Search->File->FolderIndex == 0xFFFD || Search->File->FolderIndex == 0xFFFF )
		{
		  // skip files continued from previous cab
		  DPRINT("Skipping file (%s)  FileOffset (0x%X)  LastFileOffset (0x%X).\n",
				 (char *)(Search->File + 1), Search->File->FileOffset, LastFileOffset);
		}
	  else {
		// FIXME: check for match against search criteria
		if( Search->File != Prev )
		  {
			// don't match the file we started with
			if( wcscmp( Search->Search, L"*" ) == 0 )
			  {
				// take any file
				break;
			  }
			else {
			  // otherwise, try to match the exact file name
			  RtlInitAnsiString( &AnsiString, Search->File->FileName );
			  UnicodeString.Buffer = FileName;
			  UnicodeString.Length = 0;
			  UnicodeString.MaximumLength = sizeof( FileName );
			  RtlAnsiStringToUnicodeString( &UnicodeString, &AnsiString, FALSE );
			  if( wcscmp( Search->Search, UnicodeString.Buffer ) == 0 )
				break;
			}
		  }
	  }
	  // if we make it here we found no match, so move to the next file
	  Search->Index++;
	  if( Search->Index >= PCABHeader->FileCount )
		{
		  // we have reached the end of this cabinet, try to open the next
		  DPRINT( "End of cabinet reached\n" );
		  if (wcslen(DiskNext) > 0)
			{
			  CloseCabinet();
			  
			  CabinetSetCabinetName(CabinetNext);

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -