Укажите отработанное время

Отработанное время:
Продуктивное время:
Bug 14335 - Unimplemented Function api-ms-win-core-wow64-l1-1-1.dll.IsWow64Process2   Make a simular bug
Summary: Unimplemented Function api-ms-win-core-wow64-l1-1-1.dll.IsWow64Process2
Status: RESOLVED FIXED
Alias: None
Product: WINE@Etersoft
Classification: Продукты (Products)
Component: dotNET; .NET; mono (show other bugs)
Version: unspecified
Hardware: PC Linux
: P4 minor
Target Milestone: ---
Assignee: Dmitry Timoshkov
QA Contact: Vitaly Lipatov
URL: https://docs.microsoft.com/en-us/wind...
Whiteboard:
Keywords:
Depends on:
Blocks: 14315
  Show dependency treegraph
 
In work:
Reported: 2019-12-09 19:20 MSK by Алексей Герасимов
Modified: 2020-07-01 04:28 MSK (History)
2 users (show)

See Also:
Заявки RT:
Связано с:
Дата напоминания:


Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Алексей Герасимов 2019-12-09 19:20:15 MSK
При запуске в wine 32 версии терминала
Comment 2 Алексей Герасимов 2019-12-09 19:59:02 MSK
В   /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) ?
Comment 3 Dmitry Timoshkov 2019-12-10 05:04:51 MSK
У меня несколько вопросов:
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 - это результат изначальной ошибки
и добавлять его не нужно.
Comment 4 Алексей Герасимов 2019-12-10 11:24:29 MSK
Удалось собрать 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>
Comment 5 Алексей Герасимов 2019-12-10 16:28:06 MSK
Добавил предложенную Дмитрием реализацию функции,ошибка с появлением данной функции пропала
Comment 6 Алексей Герасимов 2020-06-16 15:48:10 MSK
Закрываю как решенную
Comment 7 Vitaly Lipatov 2020-06-16 15:53:43 MSK
(Ответ Dmitry Timoshkov на комментарий #3)
> У меня несколько вопросов:
> 1. кто и как вызывает этот API?
> 2. какая версия Windows указана в winecfg?
> 
> Вопросы связаны с тем, что этот API появился только в Windows 10, и
> программы,
> поддерживающие выполнение в более ранних версиях не должны его вызывать.
...
> Однако я подозреваю, что вызов этого API - это результат изначальной ошибки
> и добавлять его не нужно.

Безусловно эта программа работает только в Windows 10 и выше, поэтому мы не будем обсуждать ошибки Microsoft, что они не те функции вызывают в своей ОС.

Дмитрий, если возможно, добавьте эту функцию в wine, должны или нет, а функция пригодится.
Comment 8 Dmitry Timoshkov 2020-06-16 16:44:22 MSK
Переоткрываю тогда.
Comment 9 Dmitry Timoshkov 2020-06-17 13:05:44 MSK
После чтения
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, при необходимости можно добавить и тесты.
Comment 10 Dmitry Timoshkov 2020-06-19 15:07:07 MSK
(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() для удаленных процессов и с этим возникли
сложности с реализацией, продолжаю работу.
Comment 11 Dmitry Timoshkov 2020-06-22 14:00:28 MSK
(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. Я пока не знаю, как решить эту проблему.
Comment 12 Dmitry Timoshkov 2020-06-26 16:08:29 MSK
(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(). Отправлю новую версию патча
в понедельник.
Comment 13 Dmitry Timoshkov 2020-06-29 15:16:14 MSK
(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 и поэтому он не видит, как это вообще можно реализовать. Ух.
Comment 14 Dmitry Timoshkov 2020-07-01 04:28:44 MSK
(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()
принята без изменений.

Отмечаю эту задачу как решенную.