Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Heap corrupted while using P/Invoked GlobalSize

I`m developing an application in C# associated with Windows clipboard. As there are many disadvantages in Dot Net Clipboard library (STA, Fail to Open Clipboard, etc. ) I dicided to use system API directly.

What I want to do is backup data of each format ( as many as possible, if not all) , push them into a stack, and later pop out to clipboard again. If you tried AutoHotKey,this is what "ClipboardAll" in it will do.

Problem presents when I tried to get the data, this is How I write for Pinvoke:

[DllImport("user32.dll", SetLastError = true)]
public static extern bool OpenClipboard(IntPtr hWndNewOwner);

[DllImport("user32.dll", SetLastError = true)]
public static extern bool CloseClipboard();

[DllImport("user32.dll")]
public static extern IntPtr GetClipboardData(uint uFormat);

[DllImport("user32.dll", SetLastError = true)]
public static extern uint EnumClipboardFormats(uint format);

[DllImport("kernel32.dll", SetLastError = true)]
public static extern IntPtr GlobalLock(IntPtr hMem);

[DllImport("kernel32.dll")]
[return: MarshalAs(UnmanagedType.Bool)]
public static extern bool GlobalUnlock(IntPtr hMem);

[DllImport("kernel32.dll")]
public static extern UIntPtr GlobalSize(IntPtr hMem);

And this is how I use them:

var x = GetFormats(); // a list returned from EnumClipboardFormats
foreach (uint format in x)
{
    IntPtr p = NativeMethods.GetClipboardData(format);
    int length = (int) NativeMethods.GlobalSize(p);
    IntPtr memPtr = NativeMethods.GlobalLock(p);
    byte[] buffer = new byte[length];
    Marshal.Copy(memPtr, buffer, 0, length);
    NativeMethods.GlobalFree(p);
    dataObject.Data[format] = buffer;//My data object
}
WinApi.CloseClipBoard();
return dataObject;

Then when I copy something in Microsoft Office Excel , I got: A Heap corrupted Exception at "GlobalSize" Method.

And after I tried to skip the format that triggered the Exception:

if(format==14||format==2) continue;

then everything worked fine.

The format 2 repsents CF_BITMAP and format 14 is CF_ENHMETAFILE, I guess they may use so-called "delay rendering" technology in clipboard, that is to say their data were null when first created and were filled when someone tried to get them, I wonder if the handle of data will change when rendering invoke, but I'm not sure.

So is there anyone can help, to find out the reason, and tell me how to fix.

like image 819
ifdog Avatar asked Oct 30 '22 17:10

ifdog


1 Answers

From the documentation:

The clipboard controls the handle that the GetClipboardData function returns, not the application. The application should copy the data immediately. The application must not free the handle nor leave it locked. The application must not use the handle after the EmptyClipboard or CloseClipboard function is called, or after the SetClipboardData function is called with the same clipboard format.

You fail to adhere to these rules. Instead of unlocking you free the handle. Don't free the handle, unlock it.

You don't perform any error checking at all. So perhaps some of the API calls fail and you do not know. Perhaps GetClipboardData is returning NULL. How would you know? Always check return values for error conditions.

There could be other errors in your program, you've not shown all the code. We can't see where you open the clipboard for instance.

like image 142
David Heffernan Avatar answered Nov 15 '22 04:11

David Heffernan