Asking for CopyMemory
is actually a pretty bad idea, if you want predictable results. For starters, no unmanaged application calls any function named CopyMemory
, as it's defined as a simple alias for the C memcpy
function in the Windows headers. There is no CopyMemory
export in kernel32.dll
at all, and whether RtlCopyMemory
is available is dependent on your platform. The logic applied for what function gets imported when you ask for CopyMemory
to be P/Invoked (if any) varies by platform. Here's a little table that applies to Windows 10:
+--------------+---------------+------------------------------+
| Platform | ExactSpelling | Resulting unmanaged function |
+--------------+---------------+------------------------------+
| .NET, 32-bit | true | - |
| .NET, 64-bit | true | - |
| .NET, 32-bit | false | RtlMoveMemory |
| .NET, 64-bit | false | memmove |
+--------------+---------------+------------------------------+
For .NET Core, the logic is much simpler: .NET Core doesn't care about this backwards compatibility nonsense. If you ask for kernel32!CopyMemory
, by golly it will try and get you kernel32!CopyMemory
. And since there is no such export at all, it will fail. This is true for both 64-bit and 32-bit runtimes.
On 64-bit Windows RtlCopyMemory
actually exists as an export, which is why that works for .NET Core (and 64-bit .NET Framework as well). It's worth noting, though, that the documentation does not guarantee that it exists at all, so it seems inadvisable to rely on this -- aside from the more basic problem that it makes your code unportable on anything that's not Windows.
From .NET 4.6 onwards, Buffer.MemoryCopy
provides a portable alternative, available in .NET Core 2.0 as well. If you must P/Invoke to a native function (hopefully only as a stopgap measure) you're better off P/Invoking to RtlMoveMemory
, since it exists on both 32-bit and 64-bit Windows:
[DllImport("kernel32.dll", EntryPoint = "RtlMoveMemory", ExactSpelling = true)]
public static extern void CopyMemory(IntPtr dest, IntPtr src, IntPtr count);
This will work correctly on both .NET Core and .NET Framework, for both bitnesses (as long as you're running on Windows, of course).
System.Buffer.MemoryCopy
– IrisirisaBuffer.MemoryCopy
, which is also available in .NET Core 2.0. Unsafe, but portable. – ImmunotherapyRtlCopyMemory
, and notCopyMemory
-- there is no such export. There may be something going on in the P/Invoke layer of the .NET CLR that fixes things up transparently, similarly to how ANSI/Unicode get conveniently translated, while .NET Core doesn't bother with such niceties (you will notice it fails on .NET too forCopyMemory
if you passExactSpelling = true
). You may as well use theRtlCopyMemory
import for both platforms. – ImmunotherapyRtlCopyMemory
works fine there, as I'd expect it to. – ImmunotherapyRtlMoveMemory
andRtlZeroMemory
, but notRtlCopyMemory
. But on an even spookier note, it has noCopyMemory
export either, so I have no idea what the CLR is doing to make this work... investing in making your code base useBuffer.MemoryCopy
seems like a really good way to move forward. :-P – Immunotherapy