Egbert
Sat May 13 15:26:51 CDT 2006
"Carl Daniel [VC++ MVP]" <cpdaniel_remove_this_and_nospam@mvps.org.nospam>
wrote in message news:e1UgLjDdGHA.4932@TK2MSFTNGP03.phx.gbl...
> Egbert Nierop (MVP for IIS) wrote:
>> "V" <vaibhav.gadodia@gmail.com> wrote in message
>> news:1147242077.506470.316990@i39g2000cwa.googlegroups.com...
>>> Hello Nathan,
>>>
>>> An excellent article on codeproject may help you. Here is the link:
>>>
http://www.codeproject.com/dotnet/ContentType.asp
>>>
>>> Regards,
>>> Vaibhav
>>
>> 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.