PtrToStringUni не работает в Windows 10 - PullRequest
0 голосов
/ 26 июня 2018

Итак, я использовал справку urlmon.dll для получения данных файлов MIME-типа, как это предлагается в Этот ответ, и он отлично работал в Windows 7.

Однако в Windows 10 тот же код генерирует System.AccessViolationException при попытке создать строку из указателя MIME.

это проблемный код:

uint mimeType;
FindMimeFromData(0, null, data, 256, null, 0, out mimeType, 0);
var mimePointer = new IntPtr(mimeType);
//Exception is thrown on the next line
var mime = Marshal.PtrToStringUni(mimePointer);

Код отлично работает на Windows7 и на тех же файлах, однако при запуске этого на windows 10 я внезапно получаю Access Violation.

Кто-нибудь еще сталкивался с этой ошибкой?

1 Ответ

0 голосов
/ 26 июня 2018
uint mimeType;
FindMimeFromData(0, null, data, 256, null, 0, out mimeType, 0);
var mimePointer = new IntPtr(mimeType);

Это, безусловно, неправильно при 64 битах ... A IntPtr - это 64 бита (это адрес памяти) ... Как может uint (32 бита) содержать его?

И если мы посмотрим на сайт pinvoke , подпись должна быть:

[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);

очень важно , в то время как документация метода очень плоха для msdn, вызов FindMimeFromData вызовет утечку памяти: вы должны освободить ppwzMimeOut, который вы получаете ... Проблема в том, что непонятно, как: здесь предлагается использовать CoTaskMemFree, то есть Marshal.FreeCoTaskMem. Я скажу, что это правильно, проверено с:

byte[] bytes = File.ReadAllBytes("someimage.jpg");

while (true)
{
    IntPtr ptr1;
    int success1 = FindMimeFromData(IntPtr.Zero, null, bytes, bytes.Length, null, 0, out ptr1, 0);
    Marshal.FreeCoTaskMem(ptr1);
}

Если я удалю Marshal.FreeCoTaskMem и посмотрю с TaskManager, память, используемая процессом, будет довольно быстро увеличиваться ... Если я восстановлю Marshal.FreeCoTaskMem, память останется стабильной.

...