ZwQueryDirectoryFile fails with STATUS_NO_MORE_FILES when listing all reparse points

Hello all,

I am trying to enumerate all reparse points that my minifilter adds to files, using a custom tag. I initially though of enumerating all the file on the volume I am interested in but after I have first searched the archives and found some very useful documentation I found that a way more easier to proceed would be to open the $Extend\$Reparse:$R:$INDEX_ALLOCATION and list all its content using ZwQueryDirectoryFile routine and from there I can identify the reparse points of interest and then perform further operations. I am opening the file with no problems but even after my minifilter had added few reparse points to files, the listing still ends with STATUS_NO_MORE_FILES. I have double checked the code I use to list the reparse points and checked the information field (IO_STATUS_BLOCK) which always gives me 0 as output of the listing. You can find down here the code that I use to perform the listing.

Is there anything I am missing? I would appreciate if anyone could help.
Thank you.

status = ZwCreateFile(&hDirRoot, GENERIC_READ | SYNCHRONIZE, &Oa, &Iosb, 0, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0);
if (!NT_SUCCESS(status))
{
LOG(“[ListAllReparsePointAndHandleThem] ZwCreateFile = 0x%x”, status);
return status;
}

pReparseInfo = ExAllocatePoolWithTag(PagedPool, uSize, REP_LISTING_TAG);
if (!ARGUMENT_PRESENT(pReparseInfo))
{
ZwClose(hDirRoot);
INFO_LOGGING(“[ListAllReparsePointAndHandleThem] ExAllocatePoolWithTag Failed”);
return STATUS_NO_MEMORY;
}

while (TRUE)
{

VIR_LOOP:
RtlZeroMemory(pReparseInfo, uSize);
status = ZwQueryDirectoryFile(hDirRoot, NULL, NULL, NULL, &Iosb, pReparseInfo, uSize, FileReparsePointInformation, FALSE, NULL, bIsStarted);
if (STATUS_BUFFER_OVERFLOW == status)
{
ExFreePoolWithTag(pReparseInfo, REP_LISTING_TAG);

uSize *= 2;
pReparseInfo = ExAllocatePoolWithTag(PagedPool, uSize, REP_LISTING_TAG);
if (ARGUMENT_PRESENT(pReparseInfo))
{
ZwClose(hDirRoot);
return STATUS_NO_MEMORY;
}

goto VIR_LOOP;
}
else
{
if (STATUS_NO_MORE_FILES == status)
{
ExFreePoolWithTag(pReparseInfo, REP_LISTING_TAG);
ZwClose(hDirRoot);
LOG(“[FileReparsePointInformation] STATUS_NO_MORE_FILES byte read %d”, Iosb.Information);
return STATUS_SUCCESS;
}
else if (STATUS_SUCCESS != status)
{
ExFreePoolWithTag(pReparseInfo, REP_LISTING_TAG);
ZwClose(hDirRoot);
return status;
}
}

if (bIsStarted)
{
unsetBoolVar(bIsStarted);
}

PFILE_REPARSE_POINT_INFORMATION repPtr = pReparseInfo;
ULONG loopLen = Iosb.Information;

while (TRUE)
{
if (repPtr->FileReference == VIR_IO_SPARSE_TAG)
{
LOG(“FileReparsePointInformation F_REF IS %I64ld TAG is %d”, repPtr->FileReference, repPtr->Tag);
}

loopLen -= sizeof(FILE_REPARSE_POINT_INFORMATION);
repPtr += sizeof(FILE_REPARSE_POINT_INFORMATION);

if (loopLen == 0)
{
break;
}
}
}

Never mind guys. I was doing a mistake here “if (repPtr->FileReference == VIR_IO_SPARSE_TAG)” where it should be “if (repPtr->Tag== VIR_IO_SPARSE_TAG)” so I was never getting the custom Tag.