Windows System Software -- Consulting, Training, Development -- Unique Expertise, Guaranteed Results

Home NTFSD
Before Posting...
Please check out the Community Guidelines in the Announcements and Administration Category.

More Info on Driver Writing and Debugging


The free OSR Learning Library has more than 50 articles on a wide variety of topics about writing and debugging device drivers and Minifilters. From introductory level to advanced. All the articles have been recently reviewed and updated, and are written using the clear and definitive style you've come to expect from OSR over the years.


Check out The OSR Learning Library at: https://www.osr.com/osr-learning-library/


Filtering IRP_MJ_DIRECTORY_CONTROL (QueryDirectory)

OSR_Community_UserOSR_Community_User Member Posts: 110,217
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;
}

Comments

  • OSR_Community_UserOSR_Community_User Member Posts: 110,217
    Hi,

    You can't change pIrp->IoStatus.Status in completion routine. Completion
    routine must return STATUS_SUCCESS or
    STATUS_MORE_PROCESSING_REQUIRED. To do what you want you need create your
    own IRP, set completion
    routine for this IRP that will signal some event
    STATUS_MORE_PROCESSING_REQUIRED and send it to file system.
    In your dispatch routine you will wait for this event, then fill original
    IRP the way you want and complete it with appropriate status.

    Best regards,
    Alexei.


    ----------
    > From: PHIL LAWSON <[email protected]>
    > To: File Systems Developers <[email protected]>
    > Subject: [ntfsd] Filtering IRP_MJ_DIRECTORY_CONTROL (QueryDirectory)
    > Date: Wednesday, April 19, 2000 3:52 AM
    >
    > 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;
    > }
    >
    >
    >
    > ---
    > You are currently subscribed to ntfsd as: [email protected]
    > To unsubscribe send a blank email to $subst('Email.Unsub')
Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. If you want to get involved, click one of these buttons!

Upcoming OSR Seminars
OSR has suspended in-person seminars due to the Covid-19 outbreak. But, don't miss your training! Attend via the internet instead!
Writing WDF Drivers 7 Dec 2020 LIVE ONLINE
Internals & Software Drivers 25 Jan 2021 LIVE ONLINE
Developing Minifilters 8 March 2021 LIVE ONLINE