unable to unload filter driver

Hi there ,

I am unable to unload my filter driver after i added the user space communication code in my driver.

I have read the forum, before posting this silly question. I know that i have to deref all objects allocated, but still, i am not able to understand why i cannot unload the driver.

To isolate the problem, i took the passthrough sample and then added some simple filter communication port code.

And i was unable to unoad the passthrough sample too. Here’s the code i added to passthrough sample:

//
// Name of port used to communicate
//

const PWSTR GuiPortName = L"\GuiPort";

//
// Gui process/port
//

PEPROCESS GuiProcess = NULL;
PFLT_PORT GuiPort = NULL;

NTSTATUS OnGuiPortConnect (
PFLT_PORT ClientPort,
__in_opt PVOID ServerPortCookie,
__in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
)
{
PAGED_CODE();

//
// Set the GUI process and port.
//

GuiProcess = PsGetCurrentProcess();
GuiPort = ClientPort;

DbgPrint(“OnGuiPortConnect: port=0x%X \n”, ClientPort);

return STATUS_SUCCESS;
}

VOID OnGuiPortDisconnect( PVOID ConnectionCookie )
{
UNREFERENCED_PARAMETER( ConnectionCookie );

PAGED_CODE();

DbgPrint( “OnGuiPortDisconnect: disconnecting port=0x%X\n”, GuiPort );

//
// Close our handle to the connection: note, since we limited max connections to 1,
// another connect will not be allowed until we return from the disconnect routine.
//

FltCloseClientPort( gFilterHandle, &GuiPort );

//
// Reset the user-process field.
//

GuiPort = NULL;
GuiProcess = NULL;

DbgPrint( “OnGuiPortDisconnect: disconnected\n” );

}

// simple func to create the comm port in driver entry

NTSTATUS CreateGuiPort()
{

OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
PSECURITY_DESCRIPTOR sd;
NTSTATUS status;

//
// Create a communication port.
//

RtlInitUnicodeString( &uniString, GuiPortName );

//
// We secure the port so only ADMINs & SYSTEM can access it.
//

status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS );

if ( !NT_SUCCESS( status ) )
{
return status;
}

InitializeObjectAttributes( &oa,
&uniString,
OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
NULL,
sd );

status = FltCreateCommunicationPort( gFilterHandle,
&GuiPort,
&oa,
NULL,
OnGuiPortConnect,
OnGuiPortDisconnect,
NULL,
1 );
//
// Free the security descriptor in all cases. It is not needed once
// the call to FltCreateCommunicationPort() is made.
//

FltFreeSecurityDescriptor( sd );

return status;

}

NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)

{
NTSTATUS status;

UNREFERENCED_PARAMETER( RegistryPath );

dprint((“DriverEntry.\n”));

//
// Register with FltMgr to tell it our callback routines
//

status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&gFilterHandle );

if(!NT_SUCCESS( status ))
{
dprint((“DriverEntry: FltRegisterFilter failed\n”));
return status;
}

//
// create communication port
//

status = CreateGuiPort();

if(!NT_SUCCESS( status ))
{
dprint((“DriverEntry: failed to create gui port\n”));

FltUnregisterFilter( gFilterHandle );

return status;
}

//
// Start filtering i/o
//

status = FltStartFiltering( gFilterHandle );

if (!NT_SUCCESS( status ))
{
dprint((“DriverEntry: failedm to start filtering.\n”));

//
// close port
//

FltCloseCommunicationPort( GuiPort );

//
// unregister filter
//

FltUnregisterFilter( gFilterHandle );
}

return status;
}

NTSTATUS
PtUnload (
__in FLT_FILTER_UNLOAD_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( Flags );

PAGED_CODE();

PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
(“PassThrough!PtUnload: Entered\n”) );

dprint((“Unload: closing communication port.\n”));

FltCloseCommunicationPort( GuiPort );

dprint((“Unload: unregistering filter.\n”));

FltUnregisterFilter( gFilterHandle );

return STATUS_SUCCESS;
}

That’s all i added to the passthrough sample. Now, whenever i open the communication port using FilterConnectCommunicationPort, i am unable to unload the driver.

Can someone help me out with this ?

Are you using the checked build on Windows? If not, you might wish to
do so, because the trace statements should be of great help in figuring
out what it is that you are not releasing any references, which is
probably the case. Using DriverVerifier would also be a good idea, if
you aren’t doing so already, for the same reasons.

What version of Windows and version of the WDK are you using?

Personally, I would first try to figure out why passthrough isn’t
unloading.

Good luck,

mm

-----Original Message-----
From: xxxxx@lists.osr.com
[mailto:xxxxx@lists.osr.com] On Behalf Of
xxxxx@gmail.com
Sent: Tuesday, August 21, 2007 16:01
To: Windows File Systems Devs Interest List
Subject: [ntfsd] unable to unload filter driver

Hi there ,

I am unable to unload my filter driver after i added the user space
communication code in my driver.

I have read the forum, before posting this silly question. I know that i
have to deref all objects allocated, but still, i am not able to
understand why i cannot unload the driver.

To isolate the problem, i took the passthrough sample and then added
some simple filter communication port code.

And i was unable to unoad the passthrough sample too. Here’s the code i
added to passthrough sample:

//
// Name of port used to communicate
//

const PWSTR GuiPortName = L"\GuiPort";

//
// Gui process/port
//

PEPROCESS GuiProcess = NULL;
PFLT_PORT GuiPort = NULL;

NTSTATUS OnGuiPortConnect (
PFLT_PORT ClientPort,
__in_opt PVOID ServerPortCookie,
__in_bcount_opt(SizeOfContext) PVOID ConnectionContext,
__in ULONG SizeOfContext,
__deref_out_opt PVOID *ConnectionCookie
)
{
PAGED_CODE();

//
// Set the GUI process and port.
//

GuiProcess = PsGetCurrentProcess();
GuiPort = ClientPort;

DbgPrint(“OnGuiPortConnect: port=0x%X \n”, ClientPort);

return STATUS_SUCCESS;
}

VOID OnGuiPortDisconnect( PVOID ConnectionCookie )
{
UNREFERENCED_PARAMETER( ConnectionCookie );

PAGED_CODE();

DbgPrint( “OnGuiPortDisconnect: disconnecting port=0x%X\n”, GuiPort
);

//
// Close our handle to the connection: note, since we limited max
connections to 1,
// another connect will not be allowed until we return from the
disconnect routine.
//

FltCloseClientPort( gFilterHandle, &GuiPort );

//
// Reset the user-process field.
//

GuiPort = NULL;
GuiProcess = NULL;

DbgPrint( “OnGuiPortDisconnect: disconnected\n” );

}

// simple func to create the comm port in driver entry

NTSTATUS CreateGuiPort()
{

OBJECT_ATTRIBUTES oa;
UNICODE_STRING uniString;
PSECURITY_DESCRIPTOR sd;
NTSTATUS status;

//
// Create a communication port.
//

RtlInitUnicodeString( &uniString, GuiPortName );

//
// We secure the port so only ADMINs & SYSTEM can access it.
//

status = FltBuildDefaultSecurityDescriptor( &sd, FLT_PORT_ALL_ACCESS
);

if ( !NT_SUCCESS( status ) )
{
return status;
}

InitializeObjectAttributes( &oa,
&uniString,
OBJ_CASE_INSENSITIVE |
OBJ_KERNEL_HANDLE,
NULL,
sd );

status = FltCreateCommunicationPort( gFilterHandle,
&GuiPort,
&oa,
NULL,
OnGuiPortConnect,
OnGuiPortDisconnect,
NULL,
1 );
//
// Free the security descriptor in all cases. It is not needed once
// the call to FltCreateCommunicationPort() is made.
//

FltFreeSecurityDescriptor( sd );

return status;

}

NTSTATUS
DriverEntry (
__in PDRIVER_OBJECT DriverObject,
__in PUNICODE_STRING RegistryPath
)

{
NTSTATUS status;

UNREFERENCED_PARAMETER( RegistryPath );

dprint((“DriverEntry.\n”));

//
// Register with FltMgr to tell it our callback routines
//

status = FltRegisterFilter( DriverObject,
&FilterRegistration,
&gFilterHandle );

if(!NT_SUCCESS( status ))
{
dprint((“DriverEntry: FltRegisterFilter failed\n”));
return status;
}

//
// create communication port
//

status = CreateGuiPort();

if(!NT_SUCCESS( status ))
{
dprint((“DriverEntry: failed to create gui port\n”));

FltUnregisterFilter( gFilterHandle );

return status;
}

//
// Start filtering i/o
//

status = FltStartFiltering( gFilterHandle );

if (!NT_SUCCESS( status ))
{
dprint((“DriverEntry: failedm to start filtering.\n”));

//
// close port
//

FltCloseCommunicationPort( GuiPort );

//
// unregister filter
//

FltUnregisterFilter( gFilterHandle );
}

return status;
}

NTSTATUS
PtUnload (
__in FLT_FILTER_UNLOAD_FLAGS Flags
)
{
UNREFERENCED_PARAMETER( Flags );

PAGED_CODE();

PT_DBG_PRINT( PTDBG_TRACE_ROUTINES,
(“PassThrough!PtUnload: Entered\n”) );

dprint((“Unload: closing communication port.\n”));

FltCloseCommunicationPort( GuiPort );

dprint((“Unload: unregistering filter.\n”));

FltUnregisterFilter( gFilterHandle );

return STATUS_SUCCESS;
}

That’s all i added to the passthrough sample. Now, whenever i open the
communication port using FilterConnectCommunicationPort, i am unable to
unload the driver.

Can someone help me out with this ?


NTFSD is sponsored by OSR

For our schedule debugging and file system seminars
(including our new fs mini-filter seminar) visit:
http://www.osr.com/seminars

You are currently subscribed to ntfsd as: xxxxx@evitechnology.com
To unsubscribe send a blank email to xxxxx@lists.osr.com

> That’s all i added to the passthrough sample. Now, whenever i open the

communication port using
FilterConnectCommunicationPort, i am unable to unload the driver.

I am not sure if this would cause the driver not to unload…but you are
closing your user mode port handle before unloading, don’t you?

Another hint will give you calling “GetLastError” after “ControlService”
fails.

Hi,

I am using WDK 6000 on win2k3 server. I almost always have the driver verifier turned on for drivers i am writing. But i did’nt get any helpful traces from verifier this time.

“but you are closing your user mode port handle before unloading, don’t you?”

Frank, i dont know if this is neccesary. I downloaded the FilterDriverDeveloperGuide.doc file from msft’s site and it says that minifilter api will handle cleaning up of pending requests.

Anyways, all handles are automatically closed on terminating the user space process. But, i tried closing the handle manually too.

But i am still no able to unload the driver :frowning:

I must be doing something silly…because minispy sample is working fine. But minispy sample is way too complex to use as a template.

Does anyone know of a simple sample explaing the working of minifilter communication objects ?

If this communication object thingy doesnt work, i am going to go the named device way… :wink:

Here’s the user space code:

#define GUI_PORT L"\GuiPort"

int main(int argc, char* argv)
{
HANDLE port;

HRESULT hr = FilterConnectCommunicationPort( GUI_PORT,
0,
NULL,
0,
NULL,
&port );

if (IS_ERROR( hr ))
{
printf(“Unable to connect to filter driver”);
return 0;
}
else
{
printf(“port opened.\n”);
}

getch();

CloseHandle(port);

printf(“port closed.\n”);

return 0;
}