I found some code from another StackOverflow answer for discovering a file's MIME type based on what's read from the first few bytes of the file. The code refers to an unmanaged method in an external DLL.
[DllImport(@"urlmon.dll", CharSet = CharSet.Auto)]
private extern static System.UInt32 FindMimeFromData(
System.UInt32 pBC,
[MarshalAs(UnmanagedType.LPStr)] System.String pwzUrl,
[MarshalAs(UnmanagedType.LPArray)] byte[] pBuffer,
System.UInt32 cbSize,
[MarshalAs(UnmanagedType.LPStr)] System.String pwzMimeProposed,
System.UInt32 dwMimeFlags,
out System.UInt32 ppwzMimeOut,
System.UInt32 dwReserverd
);
I call this method, which returns an IntPtr, and use Marshal.PtrToStringUni to read the string stored at the memory address indicated.
System.UInt32 mimetype = 0;
FindMimeFromData(0, null, buffer, maxBytes, null, 0, out mimetype, 0);
System.IntPtr mimeTypePtr = new IntPtr(mimetype);
string mime = Marshal.PtrToStringUni(mimeTypePtr);
Marshal.FreeCoTaskMem(mimeTypePtr);
Note that maxBytes is hard coded to 256 and buffer holds up to the first 256 bytes of the file being inspected.
Calling Marshal.PtrToStringUni(mimeTypePtr) throws an AccessViolationException with the message "Attempted to read or write protected memory. This is often an indication that other memory is corrupt."
The logic works fine when used in a Windows Form or Console application, so it seems like it's some security measure only applied to ASP.Net applications. Does anyone know what it would take to call this unmanaged method from ASP.Net? I would also settle for a better way to derive a file's MIME type that does not involve using the Windows Registry. I have run into a couple of problems with using the Registry, and I am trying to get this to work as a fail-over for those times when I can not rely on the Registry.