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

📄 rfsdblock.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
字号:
/*
 * COPYRIGHT:        GNU GENERAL PUBLIC LICENSE VERSION 2
 * PROJECT:          ReiserFs file system driver for Windows NT/2000/XP/Vista.
 * FILE:             rfsdblock.c
 * PURPOSE:          Disk block operations that are specific to ReiserFS.
 * PROGRAMMER:       Mark Piper, Matt Wu, Bo Brant閚.
 * HOMEPAGE:         
 * UPDATE HISTORY: 
 */

/* INCLUDES *****************************************************************/
#include <ntstatus.h>
#include "rfsd.h"

/* GLOBALS ***************************************************************/

extern PRFSD_GLOBAL RfsdGlobal;

/* DEFINITIONS *************************************************************/

#ifdef ALLOC_PRAGMA
#pragma alloc_text(PAGE, RfsdAllocateAndLoadBlock)
#pragma alloc_text(PAGE, RfsdFindItemHeaderInBlock)
#pragma alloc_text(PAGE, RfsdLoadItem)
#endif

/* FUNCTIONS *************************************************************/

/** 
 Returns the address of an allocated buffer (WHICH THE CALLER WILL BE RESPONSIBLE FOR FREEING!), filled with the contents of the given block number on disk.
 (This is really just an alternative interface to LoadBlock)
*/
PUCHAR
RfsdAllocateAndLoadBlock(
	IN	PRFSD_VCB			Vcb,
	IN	ULONG				BlockIndex)			// The ordinal block number to read
{
	// Allocate the return buffer (the caller will be responsible for freeing this!)
	PUCHAR pReturnBuffer = ExAllocatePool(NonPagedPool, Vcb->BlockSize);		// NOTE: for now, I'm switching this to non-paged, because i was getting crashes
    if (!pReturnBuffer) 
		{ DbgBreak(); return NULL; }

	// Read the block in from disk, or from cache.
	if (!RfsdLoadBlock(Vcb, BlockIndex, pReturnBuffer))
		{ DbgBreak(); ExFreePool(pReturnBuffer);  return NULL;  }	

	// Return the result to the caller.
	return pReturnBuffer;
}


/**
  Finds the item header inside a given leaf node block that matches a given key.

  STATUS_INVALID_HANDLE if the block given to search is invalid
  STATUS_NO_SUCH_MEMBER if the key is not found in the block given
*/
NTSTATUS
RfsdFindItemHeaderInBlock(
	 IN PRFSD_VCB			Vcb,
	 IN PRFSD_KEY_IN_MEMORY	pTargetKey,					// The key to match against
	 IN PUCHAR				pBlockBuffer,				// A filled disk block, provided by the caller
	 OUT PRFSD_ITEM_HEAD*	ppMatchingItemHeader,		// A pointer to a PRFSD_ITEM_HEAD.  The PRFSD_ITEM_HEAD will point to the item head matching Key, or NULL if there was no such item head in the given block.
	 IN	RFSD_KEY_COMPARISON (*fpComparisonFunction)(PRFSD_KEY_IN_MEMORY, PRFSD_KEY_IN_MEMORY)
	 )
{
	// Read the block header
	PRFSD_BLOCK_HEAD	pBlockHeader			= (PRFSD_BLOCK_HEAD) pBlockBuffer;
	PUCHAR				pItemHeaderListBuffer	= (PUCHAR) pBlockBuffer + sizeof(RFSD_BLOCK_HEAD);

	*ppMatchingItemHeader = NULL;

	// Sanity check that the block (and therefore its header) is there
	if (!pBlockHeader) { return STATUS_INVALID_HANDLE; }
	ASSERT(pBlockHeader->blk_level == 1);
	
	// Search through the item headers to find one with a key matching pTargetKey
	{
		ULONG					idxCurrentItemHeader	= 0;
		PRFSD_ITEM_HEAD			pCurrentItemHeader		= NULL;
		RFSD_KEY_IN_MEMORY		CurrentItemKey;

		for(idxCurrentItemHeader = 0; idxCurrentItemHeader < pBlockHeader->blk_nr_item; idxCurrentItemHeader++)
		{
			// Grab the item header, and its key
			pCurrentItemHeader = (PRFSD_ITEM_HEAD) (pItemHeaderListBuffer + idxCurrentItemHeader * sizeof(RFSD_ITEM_HEAD));
					
			FillInMemoryKey(
				&( pCurrentItemHeader->ih_key ), pCurrentItemHeader->ih_version, 
				&( CurrentItemKey )	);											// <
			
			// Check if this item is the one being searched for
			if ( RFSD_KEYS_MATCH == (*fpComparisonFunction)( pTargetKey , &CurrentItemKey ) )
			{
				*ppMatchingItemHeader = pCurrentItemHeader;
				return STATUS_SUCCESS;
			}
		}

		// If a matching key was never found, simply return
		return STATUS_NO_SUCH_MEMBER;
	}	
}


/** 
Given an item's key, load the block, the item header, and the item buffer associated with the key. 

STATUS_INTERNAL_ERROR				if leaf node could not be reached
STATUS_NO_SUCH_MEMBER				if the item header could not be located
STATUS_INSUFFICIENT_RESOURCES		if the leaf node buffer could not be allocated

*/
NTSTATUS
RfsdLoadItem(
	IN	 PRFSD_VCB				Vcb,
	IN   PRFSD_KEY_IN_MEMORY	pItemKey,					// The key of the item to find
	OUT  PRFSD_ITEM_HEAD*		ppMatchingItemHeader,
	OUT  PUCHAR*				ppItemBuffer,				
	OUT  PUCHAR*				ppBlockBuffer,				// Block buffer, which backs the other output data structures.  The caller must free this (even in the case of an error)!
	OPTIONAL OUT PULONG			pBlockNumber,				// The ordinal disk block number at which the item was found
	IN	RFSD_KEY_COMPARISON (*fpComparisonFunction)(PRFSD_KEY_IN_MEMORY, PRFSD_KEY_IN_MEMORY)
	)
{
	NTSTATUS	Status;
	ULONG		LeafNodeBlockNumber;		

	// Clear the output pointers
	*ppItemBuffer = *ppBlockBuffer = NULL;
	*ppMatchingItemHeader = NULL;
	if (pBlockNumber) *pBlockNumber = 0;


	// Find the block number of the leaf node bock (on disk), that should contain the item w/ pItemKey	
	Status = NavigateToLeafNode(
		Vcb, pItemKey, Vcb->SuperBlock->s_root_block, 
		&(LeafNodeBlockNumber) 
	);	
	if (!NT_SUCCESS(Status)){ DbgBreak(); return STATUS_INTERNAL_ERROR; }
	if (pBlockNumber) *pBlockNumber = LeafNodeBlockNumber;


	// Load the block (which the caller must later free)
	*ppBlockBuffer = RfsdAllocateAndLoadBlock(Vcb, LeafNodeBlockNumber);
    if (!*ppBlockBuffer) { return STATUS_INSUFFICIENT_RESOURCES; }	


	// Get the item header and its information
	Status = RfsdFindItemHeaderInBlock(
		Vcb, pItemKey, *ppBlockBuffer,
		( ppMatchingItemHeader ),			//< 
		fpComparisonFunction
	); 
	if (Status == STATUS_NO_SUCH_MEMBER)		{ return STATUS_NO_SUCH_MEMBER; }
	if (!*ppMatchingItemHeader)					{ return STATUS_INTERNAL_ERROR; }
	
	// Setup the item buffer
	*ppItemBuffer = (PUCHAR) *ppBlockBuffer + (*ppMatchingItemHeader)->ih_item_location;

	return STATUS_SUCCESS;
}





⌨️ 快捷键说明

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