Загадка
Mar 30, 2008 · CommentsПрограммированиеWow64
Вот эта программа печатает номер версии указанного пользователем модуля, который она берет из поля “FileVersion” ресурса VS_VERSION_INFO этого модуля. Имя модуля передается как первый параметр командной строки. Для работы с VS_VERSION_INFO используется стандартная библиотека version.dll.
(далее идет много кода)
#define _WIN32_WINNT 0x0501
#include <windows.h>
#include <stdio.h>
void printFileVersion(
const char* module
)
{
DWORD handle;
// Query size of the buffer we will need
DWORD size = GetFileVersionInfoSize(module, &handle);
if (size)
{
char* buffer = new char[size];
// Get own version information
BOOL res = GetFileVersionInfo(module, handle, size, buffer);
if (res)
{
void* ptr;
UINT length;
// Get FileVersion from English section of version information
res = VerQueryValue(buffer, "\\StringFileInfo\\040904B0\\FileVersion", &ptr, &length);
if (res)
{
// Print FileVersion
printf("File Version: '%s'\n", ptr);
}
}
delete[] buffer;
}
}
int __cdecl main(
int argc,
const char* argv[]
)
{
if (argc < 1 || argc > 2)
{
printf("Usage: fileversion.exe <module-name>\n");
exit(0);
}
char buffer[MAX_PATH];
DWORD size = ExpandEnvironmentStrings(argv[1], buffer, MAX_PATH);
if (size > 0 && size <= MAX_PATH)
{
printFileVersion(buffer);
}
return 0;
}
Например, для “%windir%\system32\notepad.exe” на моей машине выводится:
> fileversion.exe %windir%\system32\notepad.exe
File Version: '6.0.6000.16386 (vista_rtm.061101-2205)'
Далее, предположим, что мы пользуемся 32-х битной версией fileversion.exe и мы хотим получить версию 64-х разрядного модуля, установленного в %windir%\system32. Wow64 перенаправляет все файловые операции из %windir%\system32 в %windir%\syswow64. Соответственно, нам нужно запретить перенаправление на время чтения ресурсов из файла:
#if !defined(_WIN64)
BOOL isWow64()
{
BOOL retval = FALSE;
if (!IsWow64Process(GetCurrentProcess(), &retval))
{
retval = FALSE;
}
return retval;
}
#endif
int __cdecl main(
int argc,
const char* argv[]
)
{
if (argc < 1 || argc > 3)
{
printf("Usage: fileversion.exe <module-name> [native]\n");
exit(0);
}
#if !defined(_WIN64)
PVOID FsRedirection;
if (argc > 2 && isWow64())
{
// Disable Wow64 redirection if asked by a user
Wow64DisableWow64FsRedirection(&FsRedirection);
}
#endif
char buffer[MAX_PATH];
DWORD size = ExpandEnvironmentStrings(argv[1], buffer, MAX_PATH);
if (size > 0 && size <= MAX_PATH)
{
printFileVersion(buffer);
}
#if !defined(_WIN64)
if (argc > 2 && isWow64())
{
// Restore Wow64 redirection
Wow64RevertWow64FsRedirection(FsRedirection);
}
#endif
return 0;
}
Вопрос: почему попытка получить версию модуля может вызвать вот такое исключение при условии, что перенаправление файловой системы запрещено?
(115c.574): Unknown exception - code c06d007e (!!! second chance !!!)
KERNEL32!RaiseException+0x58:
00000000`7532f35f c9 leave
0:000:x86> k
ChildEBP RetAddr
0017fd60 00402080 KERNEL32!RaiseException+0x58
0017fdc8 0040119e rabbit!__delayLoadHelper2+0x13b [f:\sp\vctools\delayimp\delayhlp.cpp @ 331]
0017fe0c 0040115b rabbit!_tailMerge_VERSION_dll+0xd
0017ff30 004014a6 rabbit!main+0x8b [d:\projects\notepad2a\trunk\boost\rabbit\main.cpp @ 82]
0017ff80 004012fd rabbit!__tmainCRTStartup+0x1a6 [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 597]
0017ff88 7538e3f3 rabbit!mainCRTStartup+0xd [f:\sp\vctools\crt_bld\self_x86\crt\src\crtexe.c @ 414]
0017ff94 76fccfed KERNEL32!BaseThreadInitThunk+0xe
0017ffd4 76fcd1ff ntdll_76f50000!__RtlUserThreadStart+0x23
0017ffec 00000000 ntdll_76f50000!_RtlUserThreadStart+0x1b