none
Pinvoke: a few questions on DeviceIoControl and the Overlapped parameter RRS feed

  • Question

  • Hi to all,

    I have a few questions regarding "lpOverlapped" parameter of the DeviceIoControl function (pinvoke).
    I tried two ways to pass this parameter and both of them seems to work fine.
    The first one:

    ManualResetEvent stateChangeEvent = new ManualResetEvent(false);
    NativeOverlapped lpOverlapped = new NativeOverlapped();
    lpOverlapped.EventHandle = stateChangeEvent.SafeWaitHandle.DangerousGetHandle();
    int nBytesReturned;
    bool success = DeviceIoControl(cl.handle, 0x2200A0, ControlTransferByteArray, ControlTransferByteArray.Length, ControlTransferByteArray, ControlTransferByteArray.Length, out nBytesReturned, ref lpOverlapped);
    stateChangeEvent.WaitOne(timeout);
    int count;
    bool bRet = GetOverlappedResult(cl.handle, ref lpOverlapped, out count, false);
    stateChangeEvent.Close(); //Should release anything releated to memory, right ?

    The second one:

    [StructLayout(LayoutKind.Sequential)]
    public class OVERLAPPED //Changed by me from struct to class to allow to pass a null parameter to DeviceIoControl function
    {
      public IntPtr Internal;
      public IntPtr InternalHigh;
      public int Offset;
      public int OffsetHigh;
      public IntPtr hEvent;
    }
    OVERLAPPED overlapped = new OVERLAPPED();
    overlapped.hEvent = CreateEvent(IntPtr.Zero, true, false, null);
    int nBytesReturned;
    DeviceIoControl(cl.handle, 0x2200A0, ControlTransferByteArray, ControlTransferByteArray.Length, ControlTransferByteArray, ControlTransferByteArray.Length, out nBytesReturned, ref overlapped);
    UInt32 ret = WaitForSingleObject(overlapped.hEvent, timeout);
    int count;
    bool bRet = GetOverlappedResult(cl.handle, ref overlapped, out count, false);
    bool succ = CloseHandle(overlapped.hEvent); //Should release anything releated to memory, right ?
    Now, I'm new to DeviceIoControl staff and what I need to know is if there's something wrong with the above code expecially regarding memory. During the tests I have seen how is very easy to incur memory corruptions, crash or access violations with just a wrong or missing parameter.
    Even if at the end of the code, the "Close" function is called, I still feel that there's something missing and would like to know some experts comments.
    In addition to that, I had to pass to DeviceIoControl directly a buffer as byte array without any sort of marshalling. I don't know if this can be safe or not. Any help here would be also appreciated.
    I don't see any difference between the two ways except the fact that the first one does not allow me to pass null to the Overlapped parameter (easy solvable by adding an overloaded function that accept an IntPtr as parameter).

    Thanks
    Friday, March 23, 2012 2:01 AM

Answers

  • Hi Mark,

    For your first question, I agree with you, I think you understand the documentation very well. 

    And the second, yes, a managed code cannot access the un-managed memory, the CLR will provide a copy of the unmanged memory for managed code, and also make another copy of managed memory for unmanaged code. For such operation, the CLR will collect the garbage. And I think this documentation can help a lot: http://msdn.microsoft.com/en-us/library/ms973872.aspx 

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by mark_555 Wednesday, April 4, 2012 2:55 AM
    Wednesday, March 28, 2012 3:02 AM
    Moderator

All replies

  • Hi Mark,

    Welcome to the MSDN Forum.

    Based on your description, it seems that you stuck in how to clean up the unmanaged resource. 

    If so, please take a look at this documentation: http://msdn.microsoft.com/en-us/library/498928w2(v=vs.100).aspx 

    You should prevent users of your application from calling an object's Finalize method directly by limiting its scope to protected. In addition, you are strongly discouraged from calling a Finalize method for a class other than your base class directly from your application's code. To properly dispose of unmanaged resources, it is recommended that you implement a public Dispose or Close method that executes the necessary cleanup code for the object. The IDisposable interface provides the Dispose method for resource classes that implement the interface. Because it is public, users of your application can call the Dispose method directly to free memory used by unmanaged resources. When you properly implement a Dispose method, the Finalize method becomes a safeguard to clean up resources in the event that the Dispose method is not called. For more information on correct implementation, see Implementing a Dispose Method

    And this one: http://msdn.microsoft.com/en-us/library/0xy59wtx.aspx 

    The .NET Framework's garbage collector manages the allocation and release of memory for your application. Each time you create a new object, the common language runtime allocates memory for the object from the managed heap. As long as address space is available in the managed heap, the runtime continues to allocate space for new objects. However, memory is not infinite. Eventually the garbage collector must perform a collection in order to free some memory. The garbage collector's optimizing engine determines the best time to perform a collection, based upon the allocations being made. When the garbage collector performs a collection, it checks for objects in the managed heap that are no longer being used by the application and performs the necessary operations to reclaim their memory. 

    I hope this will be helpful.

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Monday, March 26, 2012 6:46 AM
    Moderator
  • Hi Mike and thanks for your suggestions. I've decided to implement the first sample because NativeOverlapped is the managed version of the unmanaged struct and should make things easier.  I've taken a look to the links and seems to be that the "stateChangeEvent.Close();" method does not need any custom implementation.
    This is what the official description say about the WaitHandle.Close method:
    "This method is the public version of the IDisposable.Dispose method implemented to support the IDisposable interface.This method releases any unmanaged resources held by the current instance.Use this method to release all resources held by an instance of WaitHandle."

    It appear to be that calling this method is enough, but please let me know if you think I'm wrong.

    Regarding the arrays of bytes that I pass directly to the function, I assume the following: I allocate the memory in the managed side and send the data to the function that returns another array of bytes filled with requested data. I assume that the function return the same block of memory allocated on the managed side and that the marshaller should free memory automatically.

    I'm not sure if this is right or not, this is the reason I opened this thread. Thanks for your help, but I still don't understand If I can leave things as is or not. Probably is better to wait for someone that know how DeviceIoControl works.

    Tuesday, March 27, 2012 10:38 PM
  • Hi Mark,

    For your first question, I agree with you, I think you understand the documentation very well. 

    And the second, yes, a managed code cannot access the un-managed memory, the CLR will provide a copy of the unmanged memory for managed code, and also make another copy of managed memory for unmanaged code. For such operation, the CLR will collect the garbage. And I think this documentation can help a lot: http://msdn.microsoft.com/en-us/library/ms973872.aspx 

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    • Marked as answer by mark_555 Wednesday, April 4, 2012 2:55 AM
    Wednesday, March 28, 2012 3:02 AM
    Moderator
  • Hi Mark,

    Do you have any update?

    Best regards,


    Mike Feng
    MSDN Community Support | Feedback to us
    Please remember to mark the replies as answers if they help and unmark them if they provide no help.

    Sunday, April 1, 2012 9:01 AM
    Moderator
  • Hi Mike and sorry for my delay.

    Thanks for your suggestions. I left the code as is and until now no problems at all. Thanks again

    Wednesday, April 4, 2012 2:55 AM