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

📄 dirctl.c

📁 This is a ReiserFs file system driver for Windows NT/2000/XP/Vista.
💻 C
📖 第 1 页 / 共 3 页
字号:
}

VOID
RfsdNotifyReportChange (
    IN PRFSD_IRP_CONTEXT IrpContext,
    IN PRFSD_VCB         Vcb,
    IN PRFSD_FCB         Fcb,
    IN ULONG             Filter,
    IN ULONG             Action   )
{
    PUNICODE_STRING FullName;
    USHORT          Offset;

    FullName = &Fcb->LongName;

    // ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);

    if (FullName->Buffer == NULL) {
        if (!RfsdGetFullFileName(Fcb->RfsdMcb, FullName)) {
            /*Status = STATUS_INSUFFICIENT_RESOURCES;*/
            return;
        }
    }

    Offset = (USHORT) ( FullName->Length - 
                        Fcb->RfsdMcb->ShortName.Length);

    FsRtlNotifyFullReportChange( Vcb->NotifySync,
                                 &(Vcb->NotifyList),
                                 (PSTRING) (FullName),
                                 (USHORT) Offset,
                                 (PSTRING)NULL,
                                 (PSTRING) NULL,
                                 (ULONG) Filter,
                                 (ULONG) Action,
                                 (PVOID) NULL );

    // ASSERT(KeGetCurrentIrql() < DISPATCH_LEVEL);
}


NTSTATUS
RfsdDirectoryControl (IN PRFSD_IRP_CONTEXT IrpContext)
{
    NTSTATUS Status;
    
    ASSERT(IrpContext);
    
    ASSERT((IrpContext->Identifier.Type == RFSDICX) &&
        (IrpContext->Identifier.Size == sizeof(RFSD_IRP_CONTEXT)));
    
    switch (IrpContext->MinorFunction) {

    case IRP_MN_QUERY_DIRECTORY:
        Status = RfsdQueryDirectory(IrpContext);
        break;

    case IRP_MN_NOTIFY_CHANGE_DIRECTORY:
        Status = RfsdNotifyChangeDirectory(IrpContext);
        break;
        
    default:
        Status = STATUS_INVALID_DEVICE_REQUEST;
        RfsdCompleteIrpContext(IrpContext, Status);
    }
    
    return Status;
}

#if DISABLE
BOOLEAN RfsdIsDirectoryEmpty (
        PRFSD_VCB Vcb,
        PRFSD_FCB Dcb )
{
DbgBreak();

    NTSTATUS                Status = STATUS_UNSUCCESSFUL;

    PRFSD_DIR_ENTRY2        pTarget = NULL;

    ULONG                   dwBytes = 0;
    ULONG                   dwRet;

    BOOLEAN                 bRet = FALSE;

    if (!IsFlagOn(Dcb->RfsdMcb->FileAttr, FILE_ATTRIBUTE_DIRECTORY)) {
        return TRUE;
    }

    __try {

        pTarget = (PRFSD_DIR_ENTRY2) ExAllocatePool(PagedPool,
                                     RFSD_DIR_REC_LEN(RFSD_NAME_LEN));
        if (!pTarget) {
            Status = STATUS_INSUFFICIENT_RESOURCES;
            __leave;
        }
        
        dwBytes = 0;

        bRet = TRUE;

        while ((LONGLONG)dwBytes < Dcb->Header.AllocationSize.QuadPart) {

            RtlZeroMemory(pTarget, RFSD_DIR_REC_LEN(RFSD_NAME_LEN));

            Status = RfsdReadInode(
                        NULL,
                        Vcb,
                        &(Dcb->RfsdMcb->Key),
                        Dcb->Inode,
                        dwBytes,
                        (PVOID)pTarget,
                        RFSD_DIR_REC_LEN(RFSD_NAME_LEN),
                        &dwRet);

            if (!NT_SUCCESS(Status)) {
                RfsdPrint((DBG_ERROR, "RfsdRemoveEntry: Reading Directory Content error.\n"));
                bRet = FALSE;
                __leave;
            }

            if (pTarget->inode) {
                if (pTarget->name_len == 1 && pTarget->name[0] == '.') {
                } else if (pTarget->name_len == 2 && pTarget->name[0] == '.' && 
                         pTarget->name[1] == '.') {
                } else {
                    bRet = FALSE;
                    break;
                }
            } else {
                break;
            }

            dwBytes += pTarget->rec_len;
        }

    } __finally {

        if (pTarget != NULL) {
            ExFreePool(pTarget);
        }
    }
    
    return bRet;
}
#endif


/**
This callback is triggered when the FS tree parser hits a leaf node that may contain a directory item.
The function then reads each dentry in the item, and is reponsible for sending them into to ProcessDirEntry.
The callback is doing work on behalf of QueryDir -- the context given is from there.
*/
// NOTE: This signature has to be changed here, at the top decleration, and in the RFSD_CALLBACK macro definition
NTSTATUS
RfsdDirectoryCallback(
		    ULONG			BlockNumber,
			PVOID			pContext)
{
	PRFSD_CALLBACK_CONTEXT	pCallbackContext = (PRFSD_CALLBACK_CONTEXT) pContext;
	RFSD_KEY_IN_MEMORY		DirectoryKey;
	PUCHAR					pBlockBuffer			= NULL;
	PRFSD_ITEM_HEAD			pDirectoryItemHeader	= NULL;
	PUCHAR					pDirectoryItemBuffer	= NULL;
	NTSTATUS				Status;

	UNICODE_STRING          InodeFileName;
	InodeFileName.Buffer = NULL;

	RfsdPrint((DBG_FUNC, __FUNCTION__ " invoked on block %i\n", BlockNumber));


	// Load the block
	pBlockBuffer = RfsdAllocateAndLoadBlock(pCallbackContext->Vcb, BlockNumber);
    if (!pBlockBuffer) { Status = STATUS_INSUFFICIENT_RESOURCES; goto out; }	

	// Construct the item key to search for
	DirectoryKey = *(pCallbackContext->pDirectoryKey);
	DirectoryKey.k_type = RFSD_KEY_TYPE_v2_DIRENTRY;

	// Get the item header and its information
	Status = RfsdFindItemHeaderInBlock(
		pCallbackContext->Vcb, &DirectoryKey, pBlockBuffer,
		( &pDirectoryItemHeader ),			//< 
		&CompareKeysWithoutOffset
	); 

	// If this block doesn't happen to contain a directory item, skip it.
	if ( (Status == STATUS_NO_SUCH_MEMBER) || !pDirectoryItemHeader )
	{ 
		KdPrint(("Block %i did not contain the appropriate diritem header\n", BlockNumber));
		Status = STATUS_SUCCESS; goto out; 
	}
	
	RfsdPrint((DBG_INFO, "Found %i dentries in block\n", pDirectoryItemHeader->u.ih_entry_count));

	// Calculate if the requested result will be from this dentry span
	// If the end of this span is not greater than the requested start, it can be skipped.
	if ( !( (pCallbackContext->idxCurrentDentry + (USHORT)(pDirectoryItemHeader->u.ih_entry_count)) > pCallbackContext->idxStartingDentry ) )
	{ 
		RfsdPrint((DBG_TRACE, "SKIPPING block\n"));

		pCallbackContext->idxCurrentDentry += pDirectoryItemHeader->u.ih_entry_count;
		Status = STATUS_SUCCESS;
		goto out;
	}



	// Otherwise, Read out each dentry, and call ProcessDirEntry on it.
	{
		BOOLEAN				bRun = TRUE;
		PRFSD_DENTRY_HEAD	pPrevDentry = NULL;
		ULONG				offsetDentry_toSequentialSpan;			// The byte offset of this dentry, relative to the dentry spans, as though only their DENTRY_HEADs were stitched together sequentially

		// Skip ahead to the starting dentry in this span.
		ULONG	idxDentryInSpan = pCallbackContext->idxStartingDentry - pCallbackContext->idxCurrentDentry;
		pCallbackContext->idxCurrentDentry += idxDentryInSpan;
		
		RfsdPrint((DBG_TRACE, "Sarting dentry: %i.  skipped to %i dentry in span\n", pCallbackContext->idxStartingDentry, idxDentryInSpan));
		
		offsetDentry_toSequentialSpan = pCallbackContext->idxCurrentDentry * sizeof(RFSD_DENTRY_HEAD);

		// Setup the item buffer
		pDirectoryItemBuffer = (PUCHAR) pBlockBuffer + pDirectoryItemHeader->ih_item_location;	


		while (bRun
			&& ( *(pCallbackContext->pUsedLength) < (pCallbackContext->BufferLength) )
			&& (idxDentryInSpan < (pDirectoryItemHeader->u.ih_entry_count)) )
		{

            STRING				OemName;				// FUTURE: does this support codepages?
			PRFSD_DENTRY_HEAD	pCurrentDentry;
			USHORT				InodeFileNameLength = 0;

			// Read a directory entry from the buffered directory item (from the file associated with the filled inode)			
			pCurrentDentry = (PRFSD_DENTRY_HEAD)  (pDirectoryItemBuffer + (idxDentryInSpan * sizeof(RFSD_DENTRY_HEAD) ));			
			
			// Skip the directory entry for the parent of the root directory (because it should not be shown, and has no stat data)
			// (NOTE: Any change made here should also be mirrored in RfsdScanDirCallback)
			if (pCurrentDentry->deh_dir_id == 0 /*&& pCurrentDentry->deh_objectid == 1*/)
			    { goto ProcessNextEntry; }
			
			// Pull the name of the file out from the buffer.
			// NOTE: The filename is not gauranteed to be null-terminated, and so the end may implicitly be the start of the previous entry.
			OemName.Buffer			= (PUCHAR) pDirectoryItemBuffer + pCurrentDentry->deh_location;
			OemName.MaximumLength	= (pPrevDentry ? pPrevDentry->deh_location :			// The end of this entry is the start of the previous
													 pDirectoryItemHeader->ih_item_len		// Otherwise this is the first entry, the end of which is the end of the item.
									  ) -  pCurrentDentry->deh_location;
			if (!pPrevDentry && pCallbackContext->idxStartingDentry > 1 && pCallbackContext->Ccb->deh_location)
			{
				if (OemName.MaximumLength != pCallbackContext->Ccb->deh_location -  pCurrentDentry->deh_location)
				{
					//KdPrint(("Changed MaximumLength from %d to %d for {%.*s}\n", OemName.MaximumLength, pCallbackContext->Ccb->deh_location -  pCurrentDentry->deh_location, RfsdStringLength(OemName.Buffer, pCallbackContext->Ccb->deh_location -  pCurrentDentry->deh_location), OemName.Buffer));
				}
				OemName.MaximumLength = pCallbackContext->Ccb->deh_location -  pCurrentDentry->deh_location;
			}
			OemName.Length			= RfsdStringLength(OemName.Buffer, OemName.MaximumLength);


			// Calculate the name's unicode length, allocate memory, and convert the codepaged name to unicode
            InodeFileNameLength = (USHORT) RfsdOEMToUnicodeSize(&OemName);            
            InodeFileName.Length = 0;
            InodeFileName.MaximumLength = InodeFileNameLength + 2;
            
            if (InodeFileNameLength <= 0) 
				{ break; }

            InodeFileName.Buffer = ExAllocatePool(
                PagedPool,
                InodeFileNameLength + 2);

            if (!InodeFileName.Buffer) {
                Status = STATUS_INSUFFICIENT_RESOURCES;
                goto out;
            }

            RtlZeroMemory(InodeFileName.Buffer, InodeFileNameLength + 2);
            
            Status = RfsdOEMToUnicode( &InodeFileName, &OemName );
			if (!NT_SUCCESS(Status))	{ Status = STATUS_INTERNAL_ERROR; goto out; }		// TODO: CHECK IF TIHS OK            

			////////////// END OF MY PART
            if (FsRtlDoesNameContainWildCards(
                &(pCallbackContext->Ccb->DirectorySearchPattern)) ?
                    FsRtlIsNameInExpression(
                        &(pCallbackContext->Ccb->DirectorySearchPattern),
                        &InodeFileName,
                        TRUE,
                        NULL) :
                !RtlCompareUnicodeString(
                    &(pCallbackContext->Ccb->DirectorySearchPattern),
                    &InodeFileName,
                    TRUE)           ) {
				// The name either contains wild cards, or matches the directory search pattern...
				                
						{
				ULONG dwBytesWritten;
				dwBytesWritten = RfsdProcessDirEntry(
                    pCallbackContext->Vcb, pCallbackContext->FileInformationClass,
                    pCurrentDentry->deh_dir_id,
					pCurrentDentry->deh_objectid,
                    pCallbackContext->Buffer,
                    *(pCallbackContext->pUsedLength),
					pCallbackContext->BufferLength - *(pCallbackContext->pUsedLength),		// The remaining length in the user's buffer
					offsetDentry_toSequentialSpan,
                    &InodeFileName,
                    pCallbackContext->ReturnSingleEntry,
					pCallbackContext->pPreviousEntry);

                if (dwBytesWritten <= 0) {
					Status = STATUS_EVENT_DONE;
                    bRun = FALSE;
					pCallbackContext->Ccb->deh_location = pPrevDentry ? pPrevDentry->deh_location : 0;
                } else {
					pCallbackContext->Ccb->deh_location = 0;
                    pCallbackContext->pPreviousEntry = (PUCHAR) (pCallbackContext->Buffer) + *(pCallbackContext->pUsedLength);
                    *(pCallbackContext->pUsedLength) += dwBytesWritten;
                }
						}
            }
            
            if (InodeFileName.Buffer) {
                ExFreePool(InodeFileName.Buffer);
                InodeFileName.Buffer = NULL;
            }


 ProcessNextEntry:            

			pPrevDentry = pCurrentDentry;

			if (bRun)
			{
				++idxDentryInSpan;				
				++(pCallbackContext->idxCurrentDentry);
				++(pCallbackContext->idxStartingDentry);
				offsetDentry_toSequentialSpan += sizeof(RFSD_DENTRY_HEAD);

				// Store the current position, so that it will be available for the next call
				pCallbackContext->Ccb->CurrentByteOffset = offsetDentry_toSequentialSpan;
			}
			

            if ( ( *(pCallbackContext->pUsedLength) > 0) && pCallbackContext->ReturnSingleEntry) {
				Status = STATUS_EVENT_DONE;
                break;
            }
            
		}

	}

 out:	
	if (pBlockBuffer)			ExFreePool(pBlockBuffer);
	if (InodeFileName.Buffer)	ExFreePool(InodeFileName.Buffer);

	return Status;
}

⌨️ 快捷键说明

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