Why does FindMimeFromData recognize image / tiff on one host, but not on another?

I am using FindMimeFromData from urlmon.dll for type MIME to nullify downloaded files. According to MIME Type Detection in Internet Explorer , image/tiff is one of the recognizable MIME types. It works fine on my development machine (Windows 7 64bit, IE9), but does not work on the test env (Windows Server 2003 R2 64bit, IE8) - it returns application/octet-stream instead of image/tiff .

The above article describes the exact steps taken to determine the MIME type, but since image/tiff is one of 26 recognized types, it must complete in step 2 (sniffing the actual data) so that file extensions and registered applications (and other registry materials) irrelevant.

Oh, and by the way, TIFF files are actually related to the program (Windows Picture and Fax Viewer) on the test server. This does not mean that TIFF links are missing from the Windows registry.

Any ideas why this is not working properly?

EDIT: FindMimeFromData is used as follows:

 public class MimeUtil { [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)] private static extern int FindMimeFromData( IntPtr pBC, [MarshalAs(UnmanagedType.LPWStr)] string pwzUrl, [MarshalAs(UnmanagedType.LPArray, ArraySubType = UnmanagedType.I1, SizeParamIndex = 3)] byte[] pBuffer, int cbSize, [MarshalAs(UnmanagedType.LPWStr)] string pwzMimeProposed, int dwMimeFlags, out IntPtr ppwzMimeOut, int dwReserved); public static string GetMimeFromData(byte[] data) { IntPtr mimetype = IntPtr.Zero; try { const int flags = 0x20; // FMFD_RETURNUPDATEDIMGMIMES int res = FindMimeFromData(IntPtr.Zero, null, data, data.Length, null, flags, out mimetype, 0); switch (res) { case 0: string mime = Marshal.PtrToStringUni(mimetype); return mime; // snip - error handling // ... default: throw new Exception("Unexpected HRESULT " + res + " returned by FindMimeFromData (in urlmon.dll)"); } } finally { if (mimetype != IntPtr.Zero) Marshal.FreeCoTaskMem(mimetype); } } } 

which is then called like this:

 protected void uploader_FileUploaded(object sender, FileUploadedEventArgs e) { int bsize = Math.Min(e.File.ContentLength, 256); byte[] buffer = new byte[bsize]; int nbytes = e.File.InputStream.Read(buffer, 0, bsize); if (nbytes > 0) string mime = MimeUtil.GetMimeFromData(buffer); // ... } 
+4
source share
1 answer

I could not reproduce your problem, however I did some research on this issue. I believe that, as you suspect, the problem is in step 2 of the MIME Type Detection: the hardcoded tests in urlmon.dll v9 are different from the hard ones in urlmon.dll v8.

The Wikipedia article on TIFF shows how complex the format is, and this has been a problem from the start:

When TIFF was introduced, its extensibility caused compatibility issues. Flexibility in coding led to jokes that TIFF means thousands of incompatible file formats.

The TIFF Compression Tag section clearly shows many of the rare compression schemes that I suspect were omitted when creating the urlmon.dll hard drive, encoded tests in earlier versions of IE.

So what can be done to solve this problem? I can think of three solutions, however each of them brings different new problems:

  • Update IE on your development computer to version 9.
  • Apply the latest IE 8 updates on your dev machine. It is well known that modified versions of urlmon.dll are often introduced (eg. KB974455 ). One of them may contain updated hard-coded MIME tests.
  • Distribute your own copy of urlmon.dll with your application.

It seems that solutions 1 and 2 are the ones you should choose. However, there may be a problem with the production environment. As my experience shows, production administrators often do not agree to install some updates for many reasons. It may be more difficult to convince the administrator to upgrade IE to v9 and simplify the installation of the IE8 KB update (as expected, but we all know how to do this). If you control production, I think you should go with solution 1.

The third solution presents two problems:

  • legal: it may be against Microsoft policy to distribute its own copy of urlmon.dll
  • : you need to load the dll dynamically to call the FindMimeFromData function or at least configure the application manifest file due to the Dynamic-Link library search order . I assume that you know that it is a very bad idea to simply manually copy the new version of urlmon.dll to the system folder, as other applications will most likely fail to use it.

In any case, good luck solving your urlmon puzzle.

+5
source

All Articles