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

Home NTDEV

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/


Security Descryptor

ArsenArsen Member Posts: 155

I created 4 events for DeviceIoControl() and wait for it with WaitForMultipleObjects() function.
But this last function does not return. It remains in the non-signaled state. I read that when calling CreateEventA () you need to assign the access right "SYNCHRONIZE".
Can anyone help me how to assign the "SYNCHRONIZE" access right to the CreateEventA() security descriptor.
And the second question.
Do I need to call GetOverlappedResult() after WaitForMultipleObjects()

Comments

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    There is not nearly enough information here. So, you created 4 events. Did you then store those events in 4 OVERLAPPED structures, and submit 4 DeviceIoControl calls using those structures? Did you open the file with FILE_FLAG_OVERLAPPED? What does the WaitForMultipleObjects call look like? Are these calls going to your own driver? You're sure the requests are being completed?

    Check the documentation. CreateEvent, by default, uses EVENT_ALL_ACCESS access rights, which includes SYNCHRONIZE.

    Yes, after WFMO returns, you must call GetOverlappedResult. Otherwise, you have no idea whether the request succeeded or failed.

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

  • ArsenArsen Member Posts: 155
    edited May 13

    Thank you. Yes, everything you said, I did, and it works correctly. Yes indeed SYNCHRONIZATION was assigned by default. As for GetOverlappedResult, the program works without it. I can not understand why, but I'll add it. WaitForMultipleObjects returns, when one or more events are signaled. And after it, when I check output buffer from overlapped DeviceIoControl, it is correct. How can I understand, WaitForMultipleObjects and GetOverlappedResult functions are for the same purpose.

    Post edited by Arsen on
  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    Yes, it works without GetOverlappedResult, but without it, you don't know whether the requests succeeded or not. That's not very good practice.

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

  • ArsenArsen Member Posts: 155
  • MBond2MBond2 Member Posts: 565

    The GetOverlappedResult function exists to extract values from the Internal and InternalHigh members of the OVERLAPPED struct. The usage of these members has become so well know, that Microsoft have even documented them so that they can be used directly. But it is still appropriate to use GetOverlappedResult because there is no reason not to do it properly

  • ArsenArsen Member Posts: 155
    edited May 19

    Thanks. Mr. Bond.

    UINT nEventSend = 0;
     while (1) {
            UINT nEvtSnd = nEventSend & MASKA;
            res = WaitForSingleObject(hEventSend[nEvtSnd], INFINITE);
            switch (res) {
    //        case WAIT_ABANDONED: std::cout << "WaitForSingleObjects returns  WAIT_ABANDONED " << std::endl; return -1;
            case WAIT_FAILED: std::cout << "WaitForSingleObjects returns  WAIT_FAILED " << GetLastError() << std::endl; return -1;
    //because  of INFINITE parameter   can not be   
    //case WAIT_TIMEOUT: std::cout << "WaitForSingleObjects returns  WAIT_TIMEOUT Error: Look to driver code" << std::endl;  return -1;
            case WAIT_OBJECT_0:
                CallConvert(BufferSend[nEvtSnd], nEvtSnd);  //its my program to alter the BufferSend[nEvtSnd]
                ResetEvent(hEventSend[nEvtSnd]);
                if (DeviceIoControl(hDevice, IOCTL_NETBUFFER_SEND, inBuffer, inBufLength, BufferSend[nEvtSnd], BUFFER_SIZE, &junk, &OverlappedSend[nEvtSnd])) {
                    std::cout << "DeviceIoControl Direct returns" << std::endl;
                    SetEvent(hEventSend[nEvtSnd]);
                }
                else {
                    switch (GetLastError()) {
                    case ERROR_IO_PENDING:
                        break;
                    default:
                        std::cout << "DeviceIoControl default Error" << std::endl;
                        return -1;
                    }
                }
                nEventSend++;
                break;
            default:
                std::cout << "WaitForSingleObject default Error" << std::endl;
                return -1;
            }
        }
    

    Where to put GetOverlappedResult. It is working fine without GetOverlappedResult.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    As the first thing in the "WAIT_OBJECT_0" case. As we've said before, if you don't do that, you don't know if the request actually succeeded.

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

  • ArsenArsen Member Posts: 155

    Thank You very much. Mr. Tim_Robers. I will think about it.

  • ArsenArsen Member Posts: 155

    Mr Tim_Robers. I finished the driver. It works well. But there is a nuance. Installs fine.
    Change adapter settings->Ethernet->Properties->Install->Service->choose my driver
    But when I try to uninstall the driver it hangs. How to understand why? Maybe I let some garbage in (not freed memory or not completed Irp. I don’t know). Please help me understand. What tools should I use to find out what the problem is

  • ArsenArsen Member Posts: 155

    And the second question. As I said, I've been getting DPC_WATCHDOG_VIOLATION when using NdisFSendNetBufferLists() in a driver dispatch routine (a single DPC or ISR has exceeded its time limit. The offending component can usually be identified with a stack trace).
    After I raised Irql before NdisFSendNetBufferLists() and lowered it after it in the dispatch procedure(level 0). And the problem is gone. Is this a good decision. Thank you

  • ArsenArsen Member Posts: 155

    In my program, two times I make large copies. One from the outgoing payload buffer to the IRP buffer, and the second from the IRP buffer to the outgoing payload buffer. whether to think about DMA. Can I use DMA instead of NdisMoveMemory()?

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    But when I try to uninstall the driver it hangs.

    Is the driver still in use when it hangs? Have you run this in a debugger to find out what's going on?

    After I raised Irql before NdisFSendNetBufferLists() and lowered it after it in the dispatch procedure(

    The average driver should not be dinking with IRQLs at all. Why do you have to be at dispatch? Is it strictly for using spin locks? Perhaps you should use some other kind of synchronization. A watchdog violation can only happen if you spend too much time at an elevated IRQL.

    Can I use DMA instead of NdisMoveMemory?

    Not for memory-to-memory moves. DMA refers to having a PCI or PCIe device do the transfers.

    (Pedants will note that there now IS a system DMA facility available on some chipsets. I discount that, because (a) it's not available on most computers, and (b) it is a limited resource and therefore cannot be relied on.)

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

  • ArsenArsen Member Posts: 155
    edited May 21
    1. I'm just learning The Windbg. No, the driver is not running.
    2. I clone all NetBufferLists in FilterSendNetBufferLists, queue them up, and send the payload to the user via a pending IRP. In the send procedure, I receive a payload with already converted data from the user, attach it to NetBufferLists from the queue, and send it to the NIC (NdisFSendNetBufferLists). I'm implementing a mutual access to the problematic data between the dispatch routine(xxxDeviceIoControl) (level 0) and the FilterSendNetBufferLists (level 2) routine by raising an Irql in the dispatch routine and using a spinlock.
    xxxDeviceIoControl (PDEVICE_OBJECT DeviceObject, PIRP Irp)
    {
    .....
    ......
    case IOCTL_NETBUFFER_SEND:
    ................
    ................
    KIRKL OldIrql;
    KeRaiseIrql(2, &OldIrql);
    NdisFSendNetBufferLists(pFilter->FilterHandle, pNBL, NDIS_DEFAULT_PORT_NUMBER, SendFlags);
    KeLowerIrql(OldIrql);
    ................
    ................
    KIRQL OldIrql;
    KeRaiseIrql(2, &OldIrql);
    FILTER_ACQUIRE_LOCK(&pFilter->Lock, TRUE);
    pFilter->IrpSpForSend[nSend] = IrpSp; //////////////???????????????
    pFilter->pIrpSend[nSend] = Irp;
    pFilter->HeadIrpSend++;
    FILTER_RELEASE_LOCK(&pFilter->Lock, TRUE);
    KeLowerIrql(OldIrql);
    ..................
    ...................
    }
    

    Thank you Mr. Tim_Roberts.

    Post edited by Arsen on
  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    Well, that's simply not right. There are essentially NO scenarios in which a driver should call KeRaiseIrql or KeLowerIrql. FILTER_ACQUIRE_LOCK will raise the IRQL for you, if it's not there already, but there's no reason why you should need to when you call NdisFSendNetBufferLists. The right answer is to figure out where your crashes are coming from, not randomly patch them.

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

  • ArsenArsen Member Posts: 155

    Well. Thank You Mr. Tim_Roberts.

  • MBond2MBond2 Member Posts: 565

    you should call GetOverlappedResult in your switch case statement in the WAIT_OBJECT_0 case. Or possibly the CallConvert function

    KeRaiseIrql may appear to solve your problem, but likely it just masks an underlying problem

  • ArsenArsen Member Posts: 155

    Yes. Thank You Mr. MBond2

  • ArsenArsen Member Posts: 155
    edited May 30

    Mr Mbond2. I took a close look at WaitForSingleObject and GetOverlappedResult. I think they are the same and when you use WaitForSingleObject there is no need to use GetOverlappedResult. I'm sorry, but if I'm wrong, please explain why you should use GetOverlappedResult.
    And second.
    You say "Or perhaps the CallConvert KeRaiseIrql function could solve your problem, but it's more likely just masking the underlying problem."
    The xxxDeviceIoControl function is a driver dispatch function, but CallConvert is in a user mode program. They are not related to each other. And in this program I have no problems. My question was about KeRaiseIrql but Mr. Tim_Roberts explained to me.
    Thank You.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    please explain why you should use GetOverlappedResult.

    Because if you don't, you have no way of knowing whether the request succeeded or failed. It is the the same as calling an API and ignoring its result.

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

  • MBond2MBond2 Member Posts: 565

    you should call GetOverlappedResult or inspect the now documented members of the OVERLAPPED struct to determine the result of your request

  • ArsenArsen Member Posts: 155

    Thanks

  • ArsenArsen Member Posts: 155

    Mr. Tim_Roberts and Mr. MBond2. What do you think. Will writing the driver in assembly language (instead of C) will increase the performance?. In 1995 we compared and got about 1.5 (Turbo C and assembler).
    Now on my computer I have about 27 for upload and the same for download without my driver. When I push my filter driver into the network stack it is 26.26. It's good or try to write on assembler.

  • Tim_RobertsTim_Roberts Member - All Emails Posts: 14,563

    No. Optimizing compilers have improved to the point that they can outperform all but the most elite assembler experts. I consider myself to be an expert, but I haven't written an assembler module in more than a decade.

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

  • MBond2MBond2 Member Posts: 565

    if your code is expected to run on one specific hardware configuration, and you have a LOT of time on your hands, you might be able to hand craft assembly code that out performs the MSVC emitted code. But you need both the certainty of the hardware platform and the sublime skill of a savant to do better. And even if you do, it will not represent an order of magnitude gain, but at most a few percentage points

    Certianty of hardware is a VERY important factor. Hardly anyone ever has this. Aerospace and medical applications might, but any commodity hardware never does. And the averages built into optimizers are usually better than hand crafted solutions - especially since the hardware guys optimize the hardware for the commonly emitted patterns

  • ArsenArsen Member Posts: 155

    Thank You Mr. Tim_Roberts and Mr. MBond2. I've stopped thinking about writing a driver in a lower level language and will try to write a driver for a USB "data converter" to call it from the NDIS Filter driver, instead of sending the data to the user mode and calling the convert function on the USB device there. I think, it will increase performance significantly.

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 19-23 June 2023 Live, Online
Writing WDF Drivers 10-14 July 2023 Live, Online
Kernel Debugging 16-20 October 2023 Live, Online
Developing Minifilters 13-17 November 2023 Live, Online