Hi
I am in the middle of writing a filter driver that filters calls from the
C:\ drive to the N:\ drive for legacy applications which don’t include
network support.
So basically if the program asks for a list of files in C:\Test then files
that are in C:\Test are displayed, and those (that aren’t already in the
C:\Test directory) in N:\Test are also displayed.
To do this I have hooked the device object, and process the
IRP_MJ_DIRECTORY_CONTROL message. The first message I get for a new
directory listing allocates some memory internally to store the network
directory and then passes the call onto the intended device driver with
IoCallDriver (). I set up a completion routine for calls to
IRP_MJ_DIRECTORY_CONTROL and the code is below.
The files I add at the end of the buffer if there is room appear in the
directory listing, but the ones I add after the STATUS_NO_MORE_FILES is
detected aren’t, and I don’t get any more requests. I assumed as I was
changing the return code to STATUS_SUCCESS and filling in the buffer
length, that it would request more files.
Does anybody know if anything else is being modified which is stopping the
search?
Any information would be greatly appreciated.
Phil Lawson
NTSTATUS RMFilterNetworkDone
(
PDEVICE_OBJECT pDeviceObject_,
PIRP pIrp_,
PVOID pContext_
)
{
PQUERY_DIRECTORY pQuery;
PIO_STACK_LOCATION pIoStackLocation;
// A request completed - look at the result
pIoStackLocation = IoGetCurrentIrpStackLocation (pIrp_);
pQuery = (PQUERY_DIRECTORY) &pIoStackLocation->Parameters.Read;
// When the request for files in a directory ends, we step in
// and fill in any extra files that may be rquired. We then return
// STATUS_SUCCESS and fill the Information field with the number of
// bytes of date we have copied
if (pIrp_->IoStatus.Status == STATUS_NO_MORE_FILES)
{
// Add the files
AddNetworkFiles (pIrp_);
// Clean up
if (pIrp_->IoStatus.Information)
{
PFILE_BOTH_DIR_INFORMATION pInfo = pIrp_->IoStatus.Status =
pIrp_->UserIosb->Status = STATUS_SUCCESS;
pIrp_->UserIosb->Information = pIrp_->IoStatus.Information;
}
else
{
// We must have added all the additional files, so we can free
// the memory we allocated to store the network file directory
ExFreePool (g_pNetworkBuffer);
g_pNetworkBuffer = NULL;
g_fulBufferType = 0L;
g_ulIrpBufferLength = 0L;
}
}
else
{
// We are still returning entries that are actually files in
// the directory requested. We need to search through the
// network directory list looking for matches. If there is a
// match then we flag that the file is already in the list
char* pData = pIrp_->UserBuffer;
PFILE_BOTH_DIR_INFORMATION pInfo = (PFILE_BOTH_DIR_INFORMATION)pData;
while (TRUE)
{
PCHAR pNetDir = g_pNetworkBuffer;
PFILE_BOTH_DIR_INFORMATION pNetwork = (PFILE_BOTH_DIR_INFORMATION)
pNetDir;
// Iterate through our network files and see if we have a match
while (TRUE)
{
// If we have a match, mark the netwrok file so that it is not added
// again at the end when we add the network files
if (wcsncmp (pInfo->FileName, pNetwork->FileName, pInfo->FileNameLength /
sizeof (WCHAR)) == 0)
{
pNetwork->FileIndex = (ULONG) -1;
break;
}
// Break out of the loop if the next entry is not valid
if (pNetwork->NextEntryOffset == 0)
break;
// Increment the network pointers
pNetDir += pNetwork->NextEntryOffset;
pNetwork = (PFILE_BOTH_DIR_INFORMATION) pNetDir;
}
// Jump out of the loop if the next entry is not valid
if (pInfo->NextEntryOffset == 0)
break;
// Increment the variables
pData += pInfo->NextEntryOffset;
pInfo = (PFILE_BOTH_DIR_INFORMATION) pData;
}
// We may be able to add some files to this buffer
if (pIrp_->IoStatus.Information < g_ulIrpBufferLength &&
!(pIoStackLocation->Flags & SL_RETURN_SINGLE_ENTRY))
{
AddNetworkFiles (pIrp_);
}
}
// Now we have to mark Irp as pending if necessary
if (pIrp_->PendingReturned)
{
IoMarkIrpPending (pIrp_);
}
// Return the status
return pIrp_->IoStatus.Status;
}