diff --git a/PInvoke/User32/WinUser.Message.cs b/PInvoke/User32/WinUser.Message.cs index b113d2c7..c64c8380 100644 --- a/PInvoke/User32/WinUser.Message.cs +++ b/PInvoke/User32/WinUser.Message.cs @@ -3104,10 +3104,35 @@ namespace Vanara.PInvoke private static IntPtr SendMessage(HWND hWnd, uint msg, IntPtr wParam, ref TLP lParam) { - using var lmem = SafeCoTaskMemHandle.CreateFromStructure(lParam); - var lret = SendMessage(hWnd, msg, wParam, lmem); - lParam = lmem.ToStructure(); - return lret; + // If this must mbe manually marshaled, do it + if (typeof(IVanaraMarshaler).IsAssignableFrom(typeof(TLP))) + return ManualMarshalSM(hWnd, msg, wParam, ref lParam); + + // Try to pin first as this is most efficient. + // This will fail just like checking for blit-ability, so take the hit once. + try + { + using var lpin = new PinnedObject(lParam); + return SendMessage(hWnd, msg, wParam, lpin); + } + catch (ArgumentException) + { + // If not blitable, manually marshal + return ManualMarshalSM(hWnd, msg, wParam, ref lParam); + } + catch + { + // For all other exceptions, throw error. + throw; + } + + static IntPtr ManualMarshalSM(HWND hWnd, uint msg, IntPtr wParam, ref TLP lParam) + { + using var lmem = SafeCoTaskMemHandle.CreateFromStructure(lParam); + var lret = SendMessage(hWnd, msg, wParam, lmem); + lParam = lmem.ToStructure(); + return lret; + } } ///