NET: Como PInvoke UpdateProcThreadAttribute
Pergunta
Eu estou tentando PInvoke UpdateProcThreadAttribute()
no Windows 7, mas minhas tentativas apenas manter retornando FALSE com um erro de Última Win32 de 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
);
Aqui está a minha tentativa da assinatura PInvoke:
[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
);
É este sensata declaração? Obrigado.
Solução
Você tem alguns problemas com a sua declaração, mas o que está lhe dando o erro não suportado é o parâmetro Atributo. A DWORD_PTR não é um ponteiro, mas sim um ponteiro tamanho inteiro sem sinal então ao invés de uint ref deve ser um IntPtr.
A declaração eu usaria é:
[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:
Eu tentei fazer isso como um comentário, mas ele não leva ao código muito bem.
Para um identificador de processo que você precisa de um IntPtr para segurar a alça. Então você precisa de algo como:
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.