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

Home NTDEV

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/


Before Posting...

Please check out the Community Guidelines in the Announcements and Administration Category.

Getting a BSOD when registering a DPC using KeSetTimer?

henrik_meidahenrik_meida Member Posts: 76
edited September 6 in NTDEV

Hi, i am getting a BSOD when registering a DPC using KeSetTimer, the code is the following:

void InitializeAndStartTimer(ULONG msec , GUID * guid) {
    KTIMER Timer = { 0 };
    KDPC TimerDpc = { 0 };

    KeInitializeTimer(&Timer);
    KeInitializeDpc(&TimerDpc,
        OnTimerExpired,
        (PVOID)guid);

    LARGE_INTEGER interval = { 0 };
    interval.QuadPart = -10000LL * msec;
    KeSetTimer(&Timer, interval, &TimerDpc);
}

BSOD happens in KeSetSystemTime because its referencing a non existence memory address ( 0x0 ), i debugged it and evreything looks OK when KeSetTimer is called, no NULL value or anything.
I call it with a 30000 msec value (to wait around 30 seconds) and a pointer to a GUID. Any Idea why would this be happening? My DPC routine never even gets called.

What is the maximum amount of time i can wait with KeSetTimer?

Comments

  • gordon_lewisgordon_lewis Member Posts: 5

    The pointers to your timer object and DPC object are on the stack. The pointers are invalid once your routine exits. So any reference to the pointers are invalid once you exit your routine. Put both objects in your device object context.

  • henrik_meidahenrik_meida Member Posts: 76

    @gordon_lewis said:
    The pointers to your timer object and DPC object are on the stack. The pointers are invalid once your routine exits. So any reference to the pointers are invalid once you exit your routine. Put both objects in your device object context.

    Can i just put them in a global variable then? if so, can i reuse them multiple time, or they have to be assigned to the same DPC as long as it has not ran yet?

    Because i might register variable amount of DPCs every minute, so one minute i might register 10 DPCs, pointing to the same function, all of which will run once after 30 second. What is the easiest way i can store the timer objects and DPC objects in this case, considering their number is variable every minute?

  • henrik_meidahenrik_meida Member Posts: 76

    One dirty workaround that came to my mind is to allocate them from NonPage pool, then pass these two as context along my GUID, then in my DPC routine after i am finished, i free them all (i allocate the GUID from non page as well). Will this work?

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,093

    This should be pretty obvious. The memory you allocate is placed on a system list, and has to remain valid until the DPC fires or is canceled.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

  • henrik_meidahenrik_meida Member Posts: 76

    @Tim_Roberts said:
    This should be pretty obvious. The memory you allocate is placed on a system list, and has to remain valid until the DPC fires or is canceled.

    So if i allocate all of them from non paged pool, and free them in my DPC, will i be fine?

    Meaning i do this:

     typedef struct _MY_CONTEXT {
        GUID  guid;
        KTIMER Timer;
        KDPC TimerDpc;
    } MY_CONTEXT , * PMY_CONTEXT;
    
    
    
    void InitializeAndStartTimer(ULONG msec , GUID  guid) {
    
        PMY_CONTEXT pMyContext = ExAllocatePoolWithTag(NonPagedPool, sizeof(MY_CONTEXT), DRIVER_TAG);
        RtlZeroMemory(pMyContext, sizeof(MY_CONTEXT));
    
        pMyContext->guid = guid;
    
        KeInitializeTimer(&pMyContext->Timer);
        KeInitializeDpc(&pMyContext->TimerDpc,
            OnTimerExpired,
            (PVOID)pMyContext);
    
        LARGE_INTEGER interval = { 0 };
        interval.QuadPart = -10000LL * msec;
        KeSetTimer(&pMyContext->Timer , interval, &pMyContext->TimerDpc);
    }
    
    
    // then at end of my DPC routine (OnTimerExpired) : 
    
    ExFreePool(pMyContext);
    
    
    

    Is this OK?

  • Peter_Viscarola_(OSR)Peter_Viscarola_(OSR) Administrator Posts: 8,663

    Yes. That’s one way that it’s usually done.

    Peter Viscarola
    OSR
    @OSRDrivers

  • henrik_meidahenrik_meida Member Posts: 76
    edited September 7

    @Peter_Viscarola_(OSR) said:
    Yes. That’s one way that it’s usually done.

    One more question:

    So since i should cancel all the pending DPCs in my unload using KeCancelTimer, what is the common approach to do this in my case considering i have random number of DPCs pending in my unload?

    Should i just also keep all the KTIMER objects in a linked list, and iterate them when my unload is called and cancel them all, or is there any better approach?

  • henrik_meidahenrik_meida Member Posts: 76

    Also what if just as i am about to cancel a DPC in my unload, it gets executed? Wouldn't there be a conflict and a possibility of BSOD?

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,093

    Yes, you will need to keep your DPCs in a list and cancel them in cleanup. Otherwise, the operating system will jump into code that is no longer there.

    If the DPC has already begun executing, KeCancelTimer will return FALSE. No big deal. What IS a big deal is if your DPC routine frees the memory while some other routine is running the list. You will have to use an interlock to protect against that.

    Tim Roberts, [email protected]
    Providenza & Boekelheide, Inc.

Sign In or Register to comment.

Howdy, Stranger!

It looks like you're new here. Sign in or register to get started.

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!
Internals & Software Drivers 15 November 2021 Live, Online
Writing WDF Drivers TBD Live, Online
Developing Minifilters 7 February 2022 Live, Online
Kernel Debugging 21 March 2022 Live, Online