none
Can I call NdisRegisterProtocolDriver from outside DriverEntry RRS feed

  • Question

  • Hi all,

    I am writing a NDIS 6.0 protocol driver, and I need to shift the call for "NdisRegisterProtocolDriver" function from Driverentry to my IOCTL handling function.

    The NDIS 6.0 guide line says "The DriverEntry function of an NDIS protocol driver must call the NdisRegisterProtocolDriver function." but to test if it is okay to delay the registration by calling it from function other than Driverentry(like I use to do it in NDIS 4.0 protocol driver) I edited the NDIS 6.0 sample protocol driver by shifting this function call in "NdisprotIoControl"(this function handles the IOCTL's) but the BSOD occurs at this call.

    What possibly wrong I am doing? Is it any limitation in NDIS 6.0 for calling "NdisRegisterProtocolDriver"?

    Monday, July 27, 2015 3:33 PM

Answers

  • It's a documentation error that it seems to require that NdisRegisterProtocolDriver be called in DriverEntry.  The documentation only means to say that that is the typical arrangement.  A protocol can legally call NdisRegisterProtocolDriver in other places.  However,

    • You must be at PASSIVE_LEVEL.
    • You must not be inside an NDIS callback (e.g., ProtocolBindAdpaterEx).
    • You must be in system process context (e.g., in a system workitem thread).

    DriverEntry meets all requirements, so if you can call from DriverEntry, do it there.

    An IOCTL is not necessarily safe, because IOCTLs can be called from usermode process context.  You might need to insert a workitem to switch to a system thread.

    At this point, it gets to be a lot of work to register the protocol from an IOCTL.  Are you sure that that is worth the complexity?  Brian's questions stand -- what's the benefit to this unusual complexity?

    Incidentally, if you break the rule and register a protocol from a non-system thread, that will probably not cause a bugcheck.  It will instead cause a potential security issue, and a potential deadlock.  So if you see a bugcheck, that's likely some other issue, and you should debug that separately.

    Monday, July 27, 2015 9:01 PM

All replies

  • What are you doing wrong? You're not following directions. It has been a requirement that you must register your protocol driver from DriverEntry for the last 15 years.

    What is the larger problem that you're trying to solve? Why do you believe that there is benefit in delaying your registration with NDIS?

     -Brian


    Azius Developer Training www.azius.com Windows device driver, internals, security, & forensics training and consulting. Blog at www.azius.com/blog

    Monday, July 27, 2015 6:34 PM
    Moderator
  • It's a documentation error that it seems to require that NdisRegisterProtocolDriver be called in DriverEntry.  The documentation only means to say that that is the typical arrangement.  A protocol can legally call NdisRegisterProtocolDriver in other places.  However,

    • You must be at PASSIVE_LEVEL.
    • You must not be inside an NDIS callback (e.g., ProtocolBindAdpaterEx).
    • You must be in system process context (e.g., in a system workitem thread).

    DriverEntry meets all requirements, so if you can call from DriverEntry, do it there.

    An IOCTL is not necessarily safe, because IOCTLs can be called from usermode process context.  You might need to insert a workitem to switch to a system thread.

    At this point, it gets to be a lot of work to register the protocol from an IOCTL.  Are you sure that that is worth the complexity?  Brian's questions stand -- what's the benefit to this unusual complexity?

    Incidentally, if you break the rule and register a protocol from a non-system thread, that will probably not cause a bugcheck.  It will instead cause a potential security issue, and a potential deadlock.  So if you see a bugcheck, that's likely some other issue, and you should debug that separately.

    Monday, July 27, 2015 9:01 PM
  • Jeffrey Tippet thanks for the reply,

    As I am upgrading the existing protocol driver which was using NDIS 4.0 to NDIS 6.0 I do have to use the existing flow and it seems it is not avoidable to shift the "NdisRegisterProtocolDriver" call out of IOCTL to driverentry.

    Now as you mentioned yes the IOCTL is called from usermode process context, so as you suggested I created system thread as 

    HANDLE		thr_handle;
    status = PsCreateSystemThread(&thr_handle,
    			THREAD_ALL_ACCESS, NULL, NULL, NULL,
    			(PKSTART_ROUTINE)myNdisRegisterProtocol, NULL);
    
    

    NTSTATUS
    myNdisRegisterProtocol()
    {
    	NTSTATUS 	status;
    	NDIS_HANDLE  ProtocolDriverContext = { 0 };
    
    	status = NdisRegisterProtocolDriver(ProtocolDriverContext,           // driver context
    		&protocolChar,
    		&Globals.NdisProtocolHandle);
    
    	if (status != NDIS_STATUS_SUCCESS)
    	{
    		status = STATUS_UNSUCCESSFUL;
    	}
    	
    	PsTerminateSystemThread(STATUS_SUCCESS);
    
    	return status;
    }

    but still the call to "NdisRegisterProtocolDriver" ends to BSOD. Do you see any issue?


    • Edited by puneDev Tuesday, July 28, 2015 2:55 PM
    Tuesday, July 28, 2015 7:06 AM
  • That's not a correct invocation of PsCreateSystemThread.  You shouldn't have to cast the function pointer type.  It's overkill to use a system thread, when a workitem will do here.

    I can't tell you why the driver bugchecks, especially when you give no detail on the actual bugcheck.  This is something you should debug on your own -- this exercise will help you learn more quickly than having somebody debug your driver for you.

    Wednesday, July 29, 2015 7:16 PM