FindMimeFromData (urlmon)
Last changed: -208.87.238.201

.
Summary
Determines the MIME type from the data provided.
Documentation

C# Signature:

    [DllImport("urlmon.dll", CharSet = CharSet.Unicode, ExactSpelling = true, SetLastError = false)]
    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);

VB.NET Signature:

VB.NET dwMimeFlags: (http://msdn.microsoft.com/en-us/library/ie/ms775107(v=vs.85).aspx)

<Flags()> Public Enum MIMEFlags As UInteger

    ''' <summary>No flags specified. Use default behavior for the function.</summary>
    [Default] = &H0
    ''' <summary>Treat the specified pwzUrl as a file name. </summary>
    URLAsFileName = &H1
    ''' <summary>Internet Explorer 6 for Windows XP SP2 and later. Use MIME-type detection even if FEATURE_MIME_SNIFFING is detected. Usually, this feature control key would disable MIME-type detection.</summary>
    EnableMIMESniffing = &H2
    ''' <summary>Internet Explorer 6 for Windows XP SP2 and later. Perform MIME-type detection if "text/plain" is proposed, even if data sniffing is otherwise disabled. Plain text may be converted to text/html if HTML tags are detected. </summary>
    IgnoreMIMETextPlain = &H4
    ''' <summary>Internet Explorer 8. Use the authoritative MIME type specified in pwzMimeProposed. Unless <see cref="MIMEFlags.IgnoreMIMETextPlain "/> is specified, no data sniffing is performed.</summary>
    ServerMIME = &H8
    ''' <summary>Internet Explorer 9. Do not perform detection if "text/plain" is specified in pwzMimeProposed.</summary>
    RespectTextPlain = &H10
    ''' <summary>Internet Explorer 9. Returns image/png and image/jpeg instead of image/x-png and image/pjpeg. </summary>
    ReturnUpdatedImgMIMEs = &H20

End Enum

    <DllImport("urlmon.dll", CharSet:=CharSet.Auto)> _
    Private Shared Function FindMimeFromData( _
        ByVal pBC As IntPtr, _
        <MarshalAs(UnmanagedType.LPWStr)> _
        ByVal pwzUrl As String, _
        <MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.I1, SizeParamIndex:=3)> ByVal _
        pBuffer As Byte(), _
        ByVal cbSize As Integer, _
        <MarshalAs(UnmanagedType.LPWStr)> _
        ByVal pwzMimeProposed As String, _
        ByVal dwMimeFlags As Integer, _
        <MarshalAs(UnmanagedType.LPWStr)> _
        ByRef ppwzMimeOut As String, _
        ByVal dwReserved As Integer) As Integer
    End Function

VB Signature:

    Public Declare Function FindMimeFromData Lib "urlmon.dll" ( _
        ByVal pbc As Long, _
        ByVal pwzUrl As String, _
        pBuffer As Any, _
        cbSize As Long, _
        ByVal pwzMimeProposed As String, _
        dwMimeFlags As Long, _
        ppwzMimeOut As Long, _
        dwReserved As Long) As Long

User-Defined Types:

None.

Notes:

VB6 Users also use these declares

Public Declare Sub CopyMemory Lib "kernel32" Alias "RtlMoveMemory" (hpvDest As Any, hpvSource As Any, ByVal cbCopy As Long)

Public Declare Function lstrlenW Lib "kernel32.dll" (ByVal lpString As Long) As Long

and this additional code

    'Convert a LPWSTR pointer to a VB string
    Private Function PtrToString(lpwString As Long) As String
        Dim Buffer() As Byte
        Dim nLen As Long

        If lpwString Then
        nLen = lstrlenW(lpwString) * 2
        If nLen Then
            ReDim Buffer(0 To (nLen - 1)) As Byte
                CopyMemory Buffer(0), ByVal lpwString, nLen
            PtrToString = Buffer
        End If
        End If
    End Function

Tips & Tricks:

Sample Code:

public string MimeTypeFrom(byte[] dataBytes, string mimeProposed) {
   if (dataBytes == null)
     throw new ArgumentNullException("dataBytes");
   string mimeRet = String.Empty;
   IntPtr suggestPtr = IntPtr.Zero, filePtr = IntPtr.Zero, outPtr = IntPtr.Zero;
   if (mimeProposed != null && mimeProposed.Length > 0) {
     //suggestPtr = Marshal.StringToCoTaskMemUni(mimeProposed); // for your experiments ;-)
     mimeRet = mimeProposed;
   }
   int ret = FindMimeFromData(IntPtr.Zero, null, dataBytes, dataBytes.Length, mimeProposed, 0, out outPtr, 0);
   if (ret == 0 && outPtr != IntPtr.Zero) {
     mimeRet = Marshal.PtrToStringUni(outPtr);
     Marshal.FreeCoTaskMem(outPtr); //msdn docs wrongly states that operator 'delete' must be used. Do not remove FreeCoTaskMem
     return mimeRet;

   }
   return mimeRet;
}

// call it this way:
Trace.Write("MimeType is " + MimeTypeFrom(Encoding.ASCII.GetBytes("%PDF-"), "text/plain"));

Alternative Managed API:

Do you know one? Please contribute it!

    /// <summary>
    /// Ensures that file exists and retrieves the content type
    /// </summary>
    /// <param name="file"></param>
    /// <returns>Returns for instance "images/jpeg" </returns>
    public static string getMimeFromFile(string file)
    {
        IntPtr mimeout;
        if (!System.IO.File.Exists(file))
        throw new FileNotFoundException(file + " not found");

        int MaxContent = (int)new FileInfo(file).Length;
        if (MaxContent > 4096) MaxContent = 4096;
        FileStream fs = File.OpenRead(file);


        byte[] buf = new byte[MaxContent];        
        fs.Read(buf, 0, MaxContent);
        fs.Close();
        int result = FindMimeFromData(IntPtr.Zero, file, buf, MaxContent, null, 0, out mimeout, 0);

        if (result != 0)
        throw Marshal.GetExceptionForHR(result);
        string mime = Marshal.PtrToStringUni(mimeout);
        Marshal.FreeCoTaskMem(mimeout);
        return mime;
    }
    //rename crystal.jpg to .gif to test functionality!
    string getImg = Environment.GetEnvironmentVariable("windir") + "\\Web\\WallPaper\\Crystal.gif";
        string mime = getMimeFromFile(getImg);

VB.NET Sample Code:

    Public Shared Function getMimeFromFile(ByVal file As String) As String
    Dim mimeout As IntPtr
    If Not System.IO.File.Exists(file) Then
        Throw New FileNotFoundException(file + " not found")
    End If
    Dim MaxContent As Integer = CInt(New FileInfo(file).Length)
    If MaxContent > 4096 Then
        MaxContent = 4096
    End If

    Dim fs As New FileStream(file, FileMode.Open)

    Dim buf(MaxContent) As Byte
    fs.Read(buf, 0, MaxContent)
    fs.Close()
    Dim result As Integer = FindMimeFromData(IntPtr.Zero, file, buf, MaxContent, Nothing, 0, mimeout, 0)

    If result <> 0 Then
        'Throw Marshal.GetHRForExceptionresult)
    End If

    Dim mime As String = Marshal.PtrToStringUni(mimeout)
    Marshal.FreeCoTaskMem(mimeout)
    Return mime
    End Function 'getMimeFromFile

    ''' <summary>
    ''' The second to last parameter errors out if its data type is set to string.
    ''' </summary>
    ''' <param name="pBC"></param>
    ''' <param name="pwzUrl"></param>
    ''' <param name="pBuffer"></param>
    ''' <param name="cbSize"></param>
    ''' <param name="pwzMimeProposed"></param>
    ''' <param name="dwMimeFlags"></param>
    ''' <param name="mimeOut"></param>
    ''' <param name="dwReserved"></param>
    ''' <returns></returns>
    <DllImport("urlmon.dll", CharSet:=CharSet.Auto)>
    Private Function FindMimeFromData(
    ByVal pBC As IntPtr,
    <MarshalAs(UnmanagedType.LPWStr)> ByVal pwzUrl As String,
    <MarshalAs(UnmanagedType.LPArray, ArraySubType:=UnmanagedType.I1, SizeParamIndex:=3)> ByVal pBuffer As Byte(),
    ByVal cbSize As Integer,
    <MarshalAs(UnmanagedType.LPWStr)> ByVal pwzMimeProposed As String,
    ByVal dwMimeFlags As Integer,
    ByRef mimeOut As IntPtr,
    ByVal dwReserved As Integer) As Integer
    End Function

    ''' <summary>
    ''' Written for use as an extension method for the byte array class.
    ''' </summary>
    ''' <param name="bytes"></param>
    ''' <param name="mimeContentType"></param>
    ''' <returns></returns>
    <Extension()>
    Public Function TryDetermineMimeType(
    bytes As Byte(),
    <Out()> ByRef mimeContentType As String) As Boolean

    Dim mimeSampleSize As Integer = 256
    Dim defaultMimeType As String = "application/octet-stream"
    Dim mimeOut As IntPtr = IntPtr.Zero
    Dim successful As Boolean = False
    mimeContentType = defaultMimeType
    Try
        FindMimeFromData(
        IntPtr.Zero,
        Nothing,
        bytes,
        Convert.ToUInt32(mimeSampleSize),
        Nothing,
        0,
        mimeOut,
        0)
        mimeContentType = Marshal.PtrToStringUni(mimeOut)
        Marshal.FreeCoTaskMem(mimeOut)
        successful = True
    Catch x As Exception
        Console.WriteLine(x.ToString())
    End Try
    Return successful
    End Function

VB6 Sample Code:

  Dim result As Long
  Dim bufferOut As String

  bufferOut = Space$(256)
  Dim buffAddr As Long
  buffAddr = StrPtr(bufferOut)

  result = FindMimeFromData(0, "file://c:/test/form1.frm", vbNullString, 0, vbNullString, 0, buffAddr, 0)
  Debug.Print PtrToString(buffAddr)