private unsafe FileVersionInfo(string fileName)
{
_fileName = fileName;
uint handle; // This variable is not used, but we need an out variable.
uint infoSize = Interop.Version.GetFileVersionInfoSizeEx(
(uint)Interop.Version.FileVersionInfoType.FILE_VER_GET_LOCALISED, _fileName, out handle);
if (infoSize != 0)
{
byte[] mem = new byte[infoSize];
fixed (byte* memPtr = mem)
{
IntPtr memIntPtr = new IntPtr((void*)memPtr);
if (Interop.Version.GetFileVersionInfoEx(
(uint)Interop.Version.FileVersionInfoType.FILE_VER_GET_LOCALISED | (uint)Interop.Version.FileVersionInfoType.FILE_VER_GET_NEUTRAL,
_fileName,
0U,
infoSize,
memIntPtr))
{
uint langid = GetVarEntry(memIntPtr);
if (!GetVersionInfoForCodePage(memIntPtr, ConvertTo8DigitHex(langid)))
{
// Some DLLs might not contain correct codepage information. In these cases we will fail during lookup.
// Explorer will take a few shots in dark by trying several specific lang-codepages
// (Explorer also randomly guesses 041D04B0=Swedish+CP_UNICODE and 040704B0=German+CP_UNICODE sometimes).
// We will try to simulate similar behavior here.
foreach (uint id in s_fallbackLanguageCodePages)
{
if (id != langid)
{
if (GetVersionInfoForCodePage(memIntPtr, ConvertTo8DigitHex(id)))
{
break;
}
}
}
}
}
}
}
}