При запуске в wine 32 версии терминала
Конечно, нужно ознакомиться с https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf-wow64apiset-iswow64process2 и https://habr.com/ru/company/infopulse/blog/308490/
В /home/alexger97/Projects/wine/dlls/api-ms-win-core-wow64-l1-1-1/api-ms-win-core-wow64-l1-1-1.spec Был добавлен по аналогии с @ stdcall IsWow64Process(ptr ptr) kernel32.IsWow64Process следующий код (при изучении документов по данной функции https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf-wow64apiset-iswow64process2) : @ stdcall IsWow64Process2(ptr ptr ptr) kernel32.IsWow64Process2 После был собран wine, но стало появляться 0009:err:module:find_forwarded_export function not found for forward 'kernel32.IsWow64Process2' used by L"C:\\windows\\system32\\api-ms-win-core-wow64-l1-1-1.dll". If you are using builtin L"api-ms-win-core-wow64-l1-1-1.dll", try using the native one instead. В kernel32/kernel32.spec есть @ stdcall -import IsWow64Process(ptr ptr) как было бы правильным обозначить IsWow64Process2(ptr ptr ptr) ?
У меня несколько вопросов: 1. кто и как вызывает этот API? 2. какая версия Windows указана в winecfg? Вопросы связаны с тем, что этот API появился только в Windows 10, и программы, поддерживающие выполнение в более ранних версиях не должны его вызывать. Касательно добавления его в Wine: .spec файл - это аналог .def файла и фактически содержит только адрес API, на который делается jmp. Для того, чтобы этот jmp работал естественно требуется написать собственно реализацию самого API в dlls/kernelbase/process.c. Например так: BOOL WINAPI DECLSPEC_HOTPATCH IsWow64Process2( HANDLE process, USHORT *process_machine, USHORT *native_machine ) { FIXME("%p, %p, %p :stub\n", process, process_machine, native_machine); *process_machine = IMAGE_FILE_MACHINE_I386; if (native_machine) *native_machine = IMAGE_FILE_MACHINE_I386; return TRUE; } После добавления его в dlls/kernelbase/kernelbase.spec нужно выполнить ./tools/make_specfiles, чтобы он автоматически добавил форварды на этот API в другие .spec файлы, включая api-ms-win-core-wow64-l1-1-0.spec и api-ms-win-core-wow64-l1-1-1.spec. Однако я подозреваю, что вызов этого API - это результат изначальной ошибки и добавлять его не нужно.
Удалось собрать WinTerminal под 64 и 32 бита, при запуске в wine возникает данная ошибка. Проект новый, еще в процессе разработки, запускаемое приложение это UWP-проект (относительно новая вещь, рассчитанная на PC для win10). ссылка на запускаемый проект : https://gitlab.eterfund.ru/alexger97/WinTerminal/tree/master/x86/Release/AppX в AppxManifest.xml зависимости : <Dependencies> <TargetDeviceFamily Name="Windows.Desktop" MinVersion="10.0.18362.0" MaxVersionTested="10.0.18362.0" /> <PackageDependency Name="Microsoft.VCLibs.140.00" MinVersion="14.0.27323.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> <PackageDependency Name="Microsoft.VCLibs.140.00.UWPDesktop" MinVersion="14.0.27323.0" Publisher="CN=Microsoft Corporation, O=Microsoft Corporation, L=Redmond, S=Washington, C=US" /> </Dependencies>
Добавил предложенную Дмитрием реализацию функции,ошибка с появлением данной функции пропала
Закрываю как решенную
(Ответ Dmitry Timoshkov на комментарий #3) > У меня несколько вопросов: > 1. кто и как вызывает этот API? > 2. какая версия Windows указана в winecfg? > > Вопросы связаны с тем, что этот API появился только в Windows 10, и > программы, > поддерживающие выполнение в более ранних версиях не должны его вызывать. ... > Однако я подозреваю, что вызов этого API - это результат изначальной ошибки > и добавлять его не нужно. Безусловно эта программа работает только в Windows 10 и выше, поэтому мы не будем обсуждать ошибки Microsoft, что они не те функции вызывают в своей ОС. Дмитрий, если возможно, добавьте эту функцию в wine, должны или нет, а функция пригодится.
Переоткрываю тогда.
После чтения https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf-wow64apiset-iswow64process2 и экспериментов я создал свою реализацию и отправил ее для принятия в winehq: https://source.winehq.org/patches/data/187205 Пара замечаний: 1. Судя по анализу мэлвари и бэктрейсам в инете реализация в Windows использует какой-то недокументированный вызов NT API, но так как естественно его описания нигде нет, то моя реализация другая. 2. Тестов я писать не стал, поведение моей реализации IsWow64Process2 следует тому, что описано в MSDN, при необходимости можно добавить и тесты.
(In reply to Dmitry Timoshkov from comment #9) > После чтения > https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf- > wow64apiset-iswow64process2 > и экспериментов я создал свою реализацию и отправил ее для принятия в winehq: > https://source.winehq.org/patches/data/187205 > > Пара замечаний: > 1. Судя по анализу мэлвари и бэктрейсам в инете реализация в Windows > использует > какой-то недокументированный вызов NT API, но так как естественно его > описания > нигде нет, то моя реализация другая. > 2. Тестов я писать не стал, поведение моей реализации IsWow64Process2 следует > тому, что описано в MSDN, при необходимости можно добавить и тесты. Так как патч не принят и комментариев на него нет, то я решил добавить тесты и отправить патч еще раз. Я взял за основу существующий тест IsWow64Process(), тесты при выполнении под Windows 10 подтвердили правильность описания MSDN и моей реализации. Однако существующие тесты для IsWow64Process() требуют поддержки в IsWow64Process2() для удаленных процессов и с этим возникли сложности с реализацией, продолжаю работу.
(In reply to Dmitry Timoshkov from comment #10) > > После чтения > > https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf- > > wow64apiset-iswow64process2 > > и экспериментов я создал свою реализацию и отправил ее для принятия в winehq: > > https://source.winehq.org/patches/data/187205 > > > > Пара замечаний: > > 1. Судя по анализу мэлвари и бэктрейсам в инете реализация в Windows > > использует > > какой-то недокументированный вызов NT API, но так как естественно его > > описания > > нигде нет, то моя реализация другая. > > 2. Тестов я писать не стал, поведение моей реализации IsWow64Process2 следует > > тому, что описано в MSDN, при необходимости можно добавить и тесты. > > Так как патч не принят и комментариев на него нет, то я решил добавить тесты > и отправить патч еще раз. Я взял за основу существующий тест > IsWow64Process(), > тесты при выполнении под Windows 10 подтвердили правильность описания MSDN и > моей реализации. Однако существующие тесты для IsWow64Process() требуют > поддержки в IsWow64Process2() для удаленных процессов и с этим возникли > сложности с реализацией, продолжаю работу. Основная проблема с поддержкой удаленных процессов в том, что согласно MSDN для работы IsWow64Process2() достаточно прав PROCESS_QUERY_INFORMATION или PROCESS_QUERY_LIMITED_INFORMATION, однако в Wine необходимо читать память процесса и для этого вызывать ReadProcessMemory(), который требует наличия доступа PROCESS_VM_READ. Я пока не знаю, как решить эту проблему.
(In reply to Dmitry Timoshkov from comment #11) > > > После чтения > > > https://docs.microsoft.com/en-us/windows/win32/api/wow64apiset/nf- > > > wow64apiset-iswow64process2 > > > и экспериментов я создал свою реализацию и отправил ее для принятия в winehq: > > > https://source.winehq.org/patches/data/187205 > > > > > > Пара замечаний: > > > 1. Судя по анализу мэлвари и бэктрейсам в инете реализация в Windows > > > использует > > > какой-то недокументированный вызов NT API, но так как естественно его > > > описания > > > нигде нет, то моя реализация другая. > > > 2. Тестов я писать не стал, поведение моей реализации IsWow64Process2 следует > > > тому, что описано в MSDN, при необходимости можно добавить и тесты. > > > > Так как патч не принят и комментариев на него нет, то я решил добавить тесты > > и отправить патч еще раз. Я взял за основу существующий тест > > IsWow64Process(), > > тесты при выполнении под Windows 10 подтвердили правильность описания MSDN и > > моей реализации. Однако существующие тесты для IsWow64Process() требуют > > поддержки в IsWow64Process2() для удаленных процессов и с этим возникли > > сложности с реализацией, продолжаю работу. > > Основная проблема с поддержкой удаленных процессов в том, что согласно MSDN > для работы IsWow64Process2() достаточно прав PROCESS_QUERY_INFORMATION или > PROCESS_QUERY_LIMITED_INFORMATION, однако в Wine необходимо читать память > процесса и для этого вызывать ReadProcessMemory(), который требует наличия > доступа PROCESS_VM_READ. Я пока не знаю, как решить эту проблему. AJ указал, что в моей реализации возможна неточность, когда вызывающий IsWow64Process2() процесс 32-битный и выполняется в WOW64, то в этом случае native_machine может содержать неверное значение. Так же AJ попросил добавить тесты. Я добавил пачку новых тестов для GetCurrentProcess() и они показали, что AJ прав и архитектура процессора в одном конкретном случае (32-битный процесс проверяет архитектуру 64-битного при выполнении в WOW64) определяется неверно. Исследование показало, что причиной этого является то, что для определения архитектуры процессора я вызываю NtQuerySystemInformation(SystemCpuInformation), а для 32-битного процесса, даже выполняемого в WOW64, он всегда возвращает PROCESSOR_ARCHITECTURE_INTEL а не PROCESSOR_ARCHITECTURE_AMD64 как я ожидал, более того, для этого даже есть тест. Пришлось изобретать новый способ определения реальной архитектуры процессора и изучать доступные варианты. Оказалось, что для есть следующие API: 1. GetSystemInfo(), который возвращает архитектуру процессора, который всегда соответствует архитектуре вызывающего процесса (32 => 32 / 64 => 64), т.е. его можно вызывать только из 64-битных процессов. 2. GetNativeSystemInfo(), который работает только для 32-битных процессов, выполняемых в WOW64. Пришлось городить огород из #ifdef _WIN64/#ifdef __i386__/#ifdef __x86_64__, которые после недолгого обдумывания удалось вполне компактно сгруппировать. Отправил новую реализацию с тестами для принятия в winehq. P.S. Когда писал отчет неожиданно понял, что моя новая реализация не учитывает один случай: выполнения 32-битного процесса в 32-битном префиксе. Т.е. для этого случая надо тоже вызывать GetSystemInfo(). Отправлю новую версию патча в понедельник.
(In reply to Dmitry Timoshkov from comment #12) > AJ указал, что в моей реализации возможна неточность, когда вызывающий > IsWow64Process2() процесс 32-битный и выполняется в WOW64, то в этом случае > native_machine может содержать неверное значение. Так же AJ попросил добавить > тесты. > > Я добавил пачку новых тестов для GetCurrentProcess() и они показали, что > AJ прав и архитектура процессора в одном конкретном случае (32-битный процесс > проверяет архитектуру 64-битного при выполнении в WOW64) определяется > неверно. > Исследование показало, что причиной этого является то, что для определения > архитектуры процессора я вызываю > NtQuerySystemInformation(SystemCpuInformation), > а для 32-битного процесса, даже выполняемого в WOW64, он всегда возвращает > PROCESSOR_ARCHITECTURE_INTEL а не PROCESSOR_ARCHITECTURE_AMD64 как я ожидал, > более того, для этого даже есть тест. > > Пришлось изобретать новый способ определения реальной архитектуры процессора > и изучать доступные варианты. Оказалось, что для есть следующие API: > 1. GetSystemInfo(), который возвращает архитектуру процессора, который > всегда соответствует архитектуре вызывающего процесса (32 => 32 / 64 => 64), > т.е. его можно вызывать только из 64-битных процессов. > 2. GetNativeSystemInfo(), который работает только для 32-битных процессов, > выполняемых в WOW64. > Пришлось городить огород из #ifdef _WIN64/#ifdef __i386__/#ifdef __x86_64__, > которые после недолгого обдумывания удалось вполне компактно сгруппировать. > > Отправил новую реализацию с тестами для принятия в winehq. > > P.S. > Когда писал отчет неожиданно понял, что моя новая реализация не учитывает > один случай: выполнения 32-битного процесса в 32-битном префиксе. Т.е. для > этого случая надо тоже вызывать GetSystemInfo(). Отправлю новую версию патча > в понедельник. Тестирование в 32-битном префиксе показало, что моя реализация работает корректно. Однако при тестировании я обратил внимание на терпящий неудачу тест NtQueryInformationProcess(ProcessImageInformation) и решил, что это надавняя поломка, связанная с тем, что AJ и компания больше не тестируют свой код в не PE сборках, и решил сделать тест на регрессию. Тест занял у меня очень много времени, даже с 'configure --disable-tests', так как в последнее время было очень много измнений в winbase.h и подобных, которые приводят к полной перекомпиляции. В результате выяснилось, что этот тест никогда не работал в ELF сборке. Чтобы результаты работы не пропали, я создал официальный баг репорт: https://bugs.winehq.org/show_bug.cgi?id=49484 AJ в нем написал, что ELF DLL никогда не создавались как mapping object в wineserver и поэтому он не видит, как это вообще можно реализовать. Ух.
(In reply to Dmitry Timoshkov from comment #12) > AJ указал, что в моей реализации возможна неточность, когда вызывающий > IsWow64Process2() процесс 32-битный и выполняется в WOW64, то в этом случае > native_machine может содержать неверное значение. Так же AJ попросил добавить > тесты. > > Я добавил пачку новых тестов для GetCurrentProcess() и они показали, что > AJ прав и архитектура процессора в одном конкретном случае (32-битный процесс > проверяет архитектуру 64-битного при выполнении в WOW64) определяется > неверно. > Исследование показало, что причиной этого является то, что для определения > архитектуры процессора я вызываю > NtQuerySystemInformation(SystemCpuInformation), > а для 32-битного процесса, даже выполняемого в WOW64, он всегда возвращает > PROCESSOR_ARCHITECTURE_INTEL а не PROCESSOR_ARCHITECTURE_AMD64 как я ожидал, > более того, для этого даже есть тест. > > Пришлось изобретать новый способ определения реальной архитектуры процессора > и изучать доступные варианты. Оказалось, что для есть следующие API: > 1. GetSystemInfo(), который возвращает архитектуру процессора, который > всегда соответствует архитектуре вызывающего процесса (32 => 32 / 64 => 64), > т.е. его можно вызывать только из 64-битных процессов. > 2. GetNativeSystemInfo(), который работает только для 32-битных процессов, > выполняемых в WOW64. > Пришлось городить огород из #ifdef _WIN64/#ifdef __i386__/#ifdef __x86_64__, > которые после недолгого обдумывания удалось вполне компактно сгруппировать. > > Отправил новую реализацию с тестами для принятия в winehq. Патч принят с небольшими изменениями в тесте, моя реализация IsWow64Process2() принята без изменений. Отмечаю эту задачу как решенную.