tags:

views:

147

answers:

1

Hi All:

I am trying to PInvoke UpdateProcThreadAttribute() on Windows 7 but my attempts just keep returning FALSE with a Last Win32 Error of 50.

Function declaration (from MSDN)

BOOL WINAPI UpdateProcThreadAttribute( __inout LPPROC_THREAD_ATTRIBUTE_LIST lpAttributeList, __in DWORD dwFlags, __in DWORD_PTR Attribute, __in PVOID lpValue, __in SIZE_T cbSize, __out_opt PVOID lpPreviousValue, __in_opt PSIZE_T lpReturnSize );

Here is my attempt at the PInvoke signature:

[DllImport("kernel32.dll", CallingConvention = CallingConvention.Winapi, SetLastError = true)] public static extern bool UpdateProcThreadAttribute ( IntPtr lpAttributeList, UInt32 dwFlags, ref UInt32 Attribute, ref IntPtr lpValue, ref IntPtr cbSize, IntPtr lpPreviousValue, IntPtr lpReturnSize );

Is this declaration sensible? Thanks.

+2  A: 

You have a few problems with your declaration but the one that is giving you the not supported error is the Attribute parameter. A DWORD_PTR is not a pointer but rather a pointer sized unsigned integer so rather than ref uint it should be an IntPtr.

The declaration I would use is:

    [DllImport("kernel32.dll", SetLastError = true)]
    [return: MarshalAs(UnmanagedType.Bool)]
    private static extern bool UpdateProcThreadAttribute(
        IntPtr lpAttributeList, uint dwFlags, IntPtr Attribute,
        IntPtr lpValue, IntPtr cbSize, IntPtr lpPreviousValue, 
        IntPtr lpReturnSize);

EDIT:

I tried to do this as a comment but it doesn't take to code very well.

For a process handle you need an IntPtr to hold the handle. So you would need something like:

IntPtr hProcess //previously retrieved.
IntPtr lpAttributeList //previously allocated using InitializeProcThreadAttributeList and Marshal.AllocHGlobal.

const int PROC_THREAD_ATTRIBUTE_PARENT_PROCESS = 0x00020000;
IntPtr lpValue = Marshal.AllocHGlobal(IntPtr.Size); 
Marshal.WriteIntPtr(lpValue, hProcess);
if(UpdateProcThreadAttribute(lpAttributeList, 0, (IntPtr)PROC_THREAD_ATTRIBUTE_PARENT_PROCESS, lpValue, (IntPtr)IntPtr.Size, IntPtr.Zero, IntPtr.Zero))
{
    //do something
}

//Free lpValue only after the lpAttributeList is deleted.
Stephen Martin
Thanks for this. I updated the signature but still get 50. How do you recommend setting up, say, lpValue to hold the handle of a process. I have it as an IntPtr (pHandle, say) so do I just pass that straight through and for cbSize do something like: IntPtr pSize = (System.IntPtr)(Marshal.SizeOf(pHandle)); ?Normally my pinvokes are OK, but this one seems particular fiendish. I am very grateful for your response. Thank you.
mrbouffant
Thanks so much. You have helped me nearly get there.. Now I get error 24 (bad length). In your example above you talked about pass IntPtr.Size as the cbSize parameter, whereas in your original post you had this as an IntPtr. I tried IntPtr lpSize = Marshal.AllocHGlobal(IntPtr.Size); Marshal.WriteInt32(lpSize, IntPtr.Size) and passing that through. Clearly it is wrong but I can't work out what the correct usage should be. Any ideas? Thanks.
mrbouffant
Sorry, I left out the conversion. It should be (IntPtr)IntPtr.Size. I've corrected the post.
Stephen Martin
Great- that worked a treat - thanks so much :)
mrbouffant