Carl Daniel said:
Egbert said:
The trick mentioned works, but not always.
The safest way is to use this.
http://technolog.nl/eprogrammer/archive/2005/12/12/415.aspx
Just one problem with that technique - it's undefined whether it actually
works. FindMimeFromData returns memory allocated from the heap with
new[],
It uses allocated memory, in the buffer and it uses CoTaskMemAlloc, for the
mimetype string. If that were a new operator, well, I'm sure that's
compatible since the C++ new keyword, after all, just uses *the same* memory
allocator (ie HeapAlloc).
so there's no way to correctly free that memory unless you can be sure
you're delete[]-ing it back into the same heap.
That's why this declaration exists.
[MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1,
SizeParamIndex = 3)] byte[] pBuffer,
int cbSize,
if it were wrong, then MS would not support it. And besides, it never failed
in my runtime.
Despite being exported from the DLL, this function really wasn't written
correctly to be used outside a known environment.
I agree, but you might agree with me, that the whole .NET framework,
**depends** on unmanaged code, from kernel, ADSI, WMI etc, and originally,
these were never made with .NET in mind. It's the other way around, .NET was
made to interop with them. So I won't hesitate to use this code, unless you
have a proven example, that shows that it will go wrong.
Maybe a CoTaskMemAlloc would be better instead of a byte[] array, but that
won't interop with FileRead...
Here you have the generated ASM listing.
00000107 FF 75 B8 push dword ptr [ebp-48h]
0000010a 56 push esi
0000010b 6A 00 push 0
0000010d 6A 00 push 0
0000010f 8D 45 B4 lea eax,[ebp-4Ch]
00000112 50 push eax
00000113 6A 00 push 0
00000115 8B D7 mov edx,edi
00000117 33 C9 xor ecx,ecx
00000119 E8 1A 2C 86 FF call FF862D38 <-- call FindMimeFromData
and here is the IL
IL_0052: ldsfld native int [mscorlib]System.IntPtr::Zero
IL_0057: ldarg.0
IL_0058: ldloc.2
IL_0059: ldloc.0
IL_005a: ldnull
IL_005b: ldc.i4.0
IL_005c: ldloca.s V_3
IL_005e: ldc.i4.0
IL_005f: call int32 TimeStampTester.Class1::FindMimeFromData(native
int, string,uint8[], int32, string, int32, string&, int32)
As you can see, the compiler does not -worry- about packing the byte array
into something else! It just assumes, that during the Pinvoke, the memory
won't move. Now this is interesting. If I have the wrong approach, then MS
introduced a dangerous bug, by allowing us to program like this.