[PATCH v15 0/2] MR706: Draft: ntoskrnl: implement cmp instruction with opcodes 0x38,0x39
fixes bug #48988 I am not very familiar with assembly, so feedback is appreciated -- v15: parent f368cdd3e9d39b2163721b7eb68a42824623e29d https://gitlab.winehq.org/wine/wine/-/merge_requests/706
From: Etaash Mathamsetty <etaash.mathamsetty(a)gmail.com> try squashing commits again fix print formatting fix potential logic error fix errors improve formatting bcrypt: Fix the non-PE build after ECDH_P384 was added. This fixes non-PE builds after 5253c8d77e8e7dc5770981e97e67348f393b99b9. Signed-off-by: Martin Storsjö <martin(a)martin.st> ddraw/tests: Add a comment to note that tests in d3d.c are deprecated. And new tests should be added to tests/ddraw{1,2,4,7}.c. ddraw/tests: Move the capability tests for enumerated devices. Move the capability tests for enumerated devices from d3d.c to ddraw{1,2,4}.c. ddraw/tests: Add more capability tests for enumerated devices. Add tests for D3DDEVCAPS_HWTRANSFORMANDLIGHT and D3DDEVCAPS_DRAWPRIMITIVES2EX. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> ddraw: Don't report unsupported device capabilities in d3d7_EnumDevices(). Fix Battle Realms: Zen Edition failing to start. The game expects to find a device without D3DDEVCAPS_HWTRANSFORMANDLIGHT. ddraw: Don't report unsupported device capabilities in d3d3_EnumDevices(). winepulse: Adapt "endpoint" struct to mmdevapi's. winepulse: Adapt "create_stream_params" struct to mmdevapi's. winepulse: Adapt "release_stream_params" struct to mmdevapi's. winepulse: Adapt "release_render_buffer_params" struct to mmdevapi's. winepulse: Adapt "get_capture_buffer_params" struct to mmdevapi's. winepulse: Adapt "get_mix_format_params" struct to mmdevapi's. winepulse: Adapt "get_device_period_params" struct to mmdevapi's. winepulse: Adapt "is_started_params" struct to mmdevapi's. winepulse: Adapt "get_prop_value_params" struct to mmdevapi's. winepulse: Switch to mmdevapi's unixlib.h. server: Use POLLIN instead of POLLPRI if the socket is in oobinline mode. server: Use check_fd_events() instead of calling poll() directly. server: Always prefer synchronous I/O in nonblocking mode. foobar2000.exe's UPnP Media Renderer component (foo_out_upnp.dll) expects that, if a select() call completes successfully with a non-empty writefds set, any immediately following send() call on a socket in the writefds set never fails with WSAEWOULDBLOCK. On Wine, the Winsock select() and send() implementations both call the Unix poll(2) under the hood to test if I/O is possible on the socket. As it turns out, it's entirely possible that Linux poll() may yield POLLOUT on the first call (by select) but *not* the second (by send), even if no send() call has been made in the meanwhile. On Linux (as of v5.19), a connected (ESTABLISHED) TCP socket that has not been shut down indicates (E)POLLOUT only if the ratio of sk_wmem_queued (the amount of bytes queued in the send buffer) to sk_sndbuf (the size of send buffer size itself, which can be retrieved via SO_SNDBUF) is below a certain threshold. Therefore, a falling edge in POLLOUT can be triggered due to a number of reasons: 1. TCP fragmentation. Once a TCP packet is split out from a larger sk_buff, it incurs extra bookkeeping overhead (e.g. sk_buff header) that is counted in sk_wmem_queued alongside application data. See also: tcp_fragment(), tso_fragment() (Linux 5.19). 2. Control packets (e.g. MTU probing). Such packets share the same buffer with application-initiated packets, and thus counted in sk_wmem_queued. See also: sk_wmem_queued_add() callers (Linux 5.19). 3. Memory pressure. This causes sk_sndbuf to shrink. See also: sk_stream_moderate_sndbuf() callers (Linux 5.19). Fix this by always attempting synchronous I/O first if req->force_async is unset and the nonblocking flag is set. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53486 msvcr100: Factor out the mapping of a context to a scheduler. Signed-off-by: Torge Matthies <tmatthies(a)codeweavers.com> msvcr100: Implement _StructuredTaskCollection::_Schedule and _Schedule_loc. Signed-off-by: Torge Matthies <tmatthies(a)codeweavers.com> msvcr100: Set scheduler in tasks created with ScheduleTask function. qasf/tests: Test ASF Reader filter initial state and pins. qasf/tests: Test ASF Reader filter threading wrt. ReceiveCanBlock. fix potential logic error improve formatting --- dlls/ddraw/ddraw.c | 12 + dlls/ddraw/tests/d3d.c | 167 +----------- dlls/ddraw/tests/ddraw1.c | 209 +++++++++++++++ dlls/ddraw/tests/ddraw2.c | 209 +++++++++++++++ dlls/ddraw/tests/ddraw4.c | 209 +++++++++++++++ dlls/ddraw/tests/ddraw7.c | 62 +++++ dlls/msvcrt/concurrency.c | 236 +++++++++++++++-- dlls/ntoskrnl.exe/instr.c | 43 ++++ dlls/qasf/tests/asfreader.c | 472 ++++++++++++++++++++++++++++++++++ dlls/winepulse.drv/mmdevdrv.c | 61 ++--- dlls/winepulse.drv/pulse.c | 143 ++++++---- dlls/winepulse.drv/unixlib.h | 263 ------------------- include/bcrypt.h | 1 + server/sock.c | 40 ++- 14 files changed, 1592 insertions(+), 535 deletions(-) delete mode 100644 dlls/winepulse.drv/unixlib.h diff --git a/dlls/ddraw/ddraw.c b/dlls/ddraw/ddraw.c index bb244222018..fd4c5bd4862 100644 --- a/dlls/ddraw/ddraw.c +++ b/dlls/ddraw/ddraw.c @@ -49,6 +49,7 @@ static struct enum_device_entry char interface_name[100]; char device_name[100]; const GUID *device_guid; + DWORD unsupported_caps; } device_list7[] = { /* T&L HAL device */ @@ -56,6 +57,7 @@ static struct enum_device_entry "WINE Direct3D7 Hardware Transform and Lighting acceleration using WineD3D", "Wine D3D7 T&L HAL", &IID_IDirect3DTnLHalDevice, + 0, }, /* HAL device */ @@ -63,6 +65,7 @@ static struct enum_device_entry "WINE Direct3D7 Hardware acceleration using WineD3D", "Direct3D HAL", &IID_IDirect3DHALDevice, + D3DDEVCAPS_HWTRANSFORMANDLIGHT, }, /* RGB device */ @@ -70,6 +73,7 @@ static struct enum_device_entry "WINE Direct3D7 RGB Software Emulation using WineD3D", "Wine D3D7 RGB", &IID_IDirect3DRGBDevice, + D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_DRAWPRIMITIVES2EX, }, }; @@ -3757,6 +3761,7 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA { struct ddraw *ddraw = impl_from_IDirect3D7(iface); D3DDEVICEDESC7 device_desc7; + DWORD dev_caps; HRESULT hr; size_t i; @@ -3772,12 +3777,14 @@ static HRESULT WINAPI d3d7_EnumDevices(IDirect3D7 *iface, LPD3DENUMDEVICESCALLBA wined3d_mutex_unlock(); return hr; } + dev_caps = device_desc7.dwDevCaps; for (i = 0; i < ARRAY_SIZE(device_list7); i++) { HRESULT ret; device_desc7.deviceGUID = *device_list7[i].device_guid; + device_desc7.dwDevCaps = dev_caps & ~device_list7[i].unsupported_caps; ret = callback(device_list7[i].interface_name, device_list7[i].device_name, &device_desc7, context); if (ret != DDENUMRET_OK) { @@ -3875,6 +3882,9 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA hal_desc.dcmColorModel = 0; /* RGB, RAMP and MMX devices cannot report HAL hardware flags */ hal_desc.dwFlags = 0; + /* RGB, REF, RAMP and MMX devices don't report hardware transform and lighting capability */ + hal_desc.dwDevCaps &= ~(D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_DRAWPRIMITIVES2EX); + hel_desc.dwDevCaps &= ~(D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_DRAWPRIMITIVES2EX); hr = callback((GUID *)&IID_IDirect3DRGBDevice, reference_description, device_name, &hal_desc, &hel_desc, context); @@ -3899,6 +3909,8 @@ static HRESULT WINAPI d3d3_EnumDevices(IDirect3D3 *iface, LPD3DENUMDEVICESCALLBA | D3DPTEXTURECAPS_NONPOW2CONDITIONAL | D3DPTEXTURECAPS_PERSPECTIVE); /* HAL devices have a HEL dcmColorModel of 0 */ hel_desc.dcmColorModel = 0; + /* HAL devices report hardware transform and lighting capability, but not in hel */ + hel_desc.dwDevCaps &= ~(D3DDEVCAPS_HWTRANSFORMANDLIGHT | D3DDEVCAPS_DRAWPRIMITIVES2EX); hr = callback((GUID *)&IID_IDirect3DHALDevice, wined3d_description, device_name, &hal_desc, &hel_desc, context); diff --git a/dlls/ddraw/tests/d3d.c b/dlls/ddraw/tests/d3d.c index 87d0648b699..09708f22d57 100644 --- a/dlls/ddraw/tests/d3d.c +++ b/dlls/ddraw/tests/d3d.c @@ -488,133 +488,6 @@ static void SceneTest(void) /* TODO: Verify that blitting works in the same way as in d3d9 */ } -static HRESULT WINAPI enumDevicesCallback(GUID *Guid, char *DeviceDescription, - char *DeviceName, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx) -{ - UINT ver = *((UINT *) ctx); - if(IsEqualGUID(&IID_IDirect3DRGBDevice, Guid)) - { - ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, - "RGB Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, - "RGB Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, - "RGB Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, - "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); - - ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, - "RGB Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, - "RGB Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, - "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, - "RGB Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - - ok(hal->dcmColorModel == 0, "RGB Device %u hal caps has colormodel %lu\n", ver, hal->dcmColorModel); - ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device %u hel caps has colormodel %lu\n", ver, hel->dcmColorModel); - - ok(hal->dwFlags == 0, "RGB Device %u hal caps has hardware flags %#lx\n", ver, hal->dwFlags); - ok(hel->dwFlags != 0, "RGB Device %u hel caps has hardware flags %#lx\n", ver, hel->dwFlags); - } - else if(IsEqualGUID(&IID_IDirect3DHALDevice, Guid)) - { - trace("HAL Device %d\n", ver); - ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device %u hal caps has colormodel %lu\n", ver, hel->dcmColorModel); - ok(hel->dcmColorModel == 0, "HAL Device %u hel caps has colormodel %lu\n", ver, hel->dcmColorModel); - - ok(hal->dwFlags != 0, "HAL Device %u hal caps has hardware flags %#lx\n", ver, hal->dwFlags); - ok(hel->dwFlags != 0, "HAL Device %u hel caps has hardware flags %#lx\n", ver, hel->dwFlags); - } - else if(IsEqualGUID(&IID_IDirect3DRefDevice, Guid)) - { - ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, - "REF Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, - "REF Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, - "REF Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, - "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); - - ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, - "REF Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, - "REF Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, - "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, - "REF Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - } - else if(IsEqualGUID(&IID_IDirect3DRampDevice, Guid)) - { - ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, - "Ramp Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, - "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, - "Ramp Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, - "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); - - ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, - "Ramp Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, - "Ramp Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, - "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, - "Ramp Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - - ok(hal->dcmColorModel == 0, "Ramp Device %u hal caps has colormodel %lu\n", ver, hal->dcmColorModel); - ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device %u hel caps has colormodel %lu\n", - ver, hel->dcmColorModel); - - ok(hal->dwFlags == 0, "Ramp Device %u hal caps has hardware flags %#lx\n", ver, hal->dwFlags); - ok(hel->dwFlags != 0, "Ramp Device %u hel caps has hardware flags %#lx\n", ver, hel->dwFlags); - } - else if(IsEqualGUID(&IID_IDirect3DMMXDevice, Guid)) - { - ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, - "MMX Device %d hal line caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, - "MMX Device %d hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, - "MMX Device %d hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); - ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, - "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n", ver); - - ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, - "MMX Device %d hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, - "MMX Device %d hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, - "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, - "MMX Device %d hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n", ver); - - ok(hal->dcmColorModel == 0, "MMX Device %u hal caps has colormodel %lu\n", ver, hal->dcmColorModel); - ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device %u hel caps has colormodel %lu\n", ver, hel->dcmColorModel); - - ok(hal->dwFlags == 0, "MMX Device %u hal caps has hardware flags %#lx\n", ver, hal->dwFlags); - ok(hel->dwFlags != 0, "MMX Device %u hel caps has hardware flags %#lx\n", ver, hel->dwFlags); - } - else - { - ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", DeviceDescription, DeviceName); - if(hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal line has pow2 set\n"); - else trace("hal line does NOT have pow2 set\n"); - if(hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hal tri has pow2 set\n"); - else trace("hal tri does NOT have pow2 set\n"); - if(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel line has pow2 set\n"); - else trace("hel line does NOT have pow2 set\n"); - if(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) trace("hel tri has pow2 set\n"); - else trace("hel tri does NOT have pow2 set\n"); - } - return DDENUMRET_OK; -} - static HRESULT WINAPI enumDevicesCallbackTest7(char *DeviceDescription, char *DeviceName, D3DDEVICEDESC7 *lpdd7, void *Context) { @@ -774,43 +647,6 @@ static void D3D7EnumLifetimeTest(void) } } -static void CapsTest(void) -{ - IDirect3D3 *d3d3; - IDirect3D3 *d3d2; - IDirectDraw *dd1; - HRESULT hr; - UINT ver; - - hr = DirectDrawCreate(NULL, &dd1, NULL); - ok(hr == DD_OK, "Got hr %#lx.\n", hr); - hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D3, (void **) &d3d3); - ok(hr == D3D_OK, "Got hr %#lx.\n", hr); - - hr = IDirect3D3_EnumDevices(d3d3, NULL, NULL); - ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr); - - ver = 3; - IDirect3D3_EnumDevices(d3d3, enumDevicesCallback, &ver); - - IDirect3D3_Release(d3d3); - IDirectDraw_Release(dd1); - - hr = DirectDrawCreate(NULL, &dd1, NULL); - ok(hr == DD_OK, "Got hr %#lx.\n", hr); - hr = IDirectDraw_QueryInterface(dd1, &IID_IDirect3D2, (void **) &d3d2); - ok(hr == D3D_OK, "Got hr %#lx.\n", hr); - - hr = IDirect3D2_EnumDevices(d3d2, NULL, NULL); - ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr); - - ver = 2; - IDirect3D2_EnumDevices(d3d2, enumDevicesCallback, &ver); - - IDirect3D2_Release(d3d2); - IDirectDraw_Release(dd1); -} - struct v_in { float x, y, z; }; @@ -2227,6 +2063,8 @@ START_TEST(d3d) }; unsigned int i; + /* These tests are deprecated. New tests should be added to tests/ddraw{1,2,4,7}.c */ + init_function_pointers(); if(!pDirectDrawCreateEx) { win_skip("function DirectDrawCreateEx not available\n"); @@ -2241,7 +2079,6 @@ START_TEST(d3d) D3D7EnumTest(); D3D7EnumLifetimeTest(); SetMaterialTest(); - CapsTest(); VertexBufferDescTest(); SetRenderTargetTest(); VertexBufferLockRest(); diff --git a/dlls/ddraw/tests/ddraw1.c b/dlls/ddraw/tests/ddraw1.c index 1629660aedc..94d41dbc34d 100644 --- a/dlls/ddraw/tests/ddraw1.c +++ b/dlls/ddraw/tests/ddraw1.c @@ -15145,6 +15145,214 @@ static void test_filling_convention(void) DestroyWindow(window); } +static HRESULT WINAPI test_enum_devices_caps_callback(GUID *guid, char *device_desc, + char *device_name, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx) +{ + if(IsEqualGUID(&IID_IDirect3DRGBDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "RGB Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "RGB Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "RGB Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "RGB Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "RGB Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "RGB Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags == 0, "RGB Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "RGB Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DHALDevice, guid)) + { + ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device hal caps has colormodel %lu\n", hel->dcmColorModel); + ok(hel->dcmColorModel == 0, "HAL Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags != 0, "HAL Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "HAL Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok(hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT, + "HAL Device hal device caps does not have D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok(hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX, + "HAL Device hal device caps does not have D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DRefDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "REF Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "REF Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "REF Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "REF Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "REF Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "REF Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "REF Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "REF Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "REF Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DRampDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "Ramp Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "Ramp Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "Ramp Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "Ramp Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "Ramp Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "Ramp Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device hel caps has colormodel %lu\n", + hel->dcmColorModel); + + ok(hal->dwFlags == 0, "Ramp Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "Ramp Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "Ramp Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "Ramp Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "Ramp Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "Ramp Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DMMXDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "MMX Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "MMX Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "MMX Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "MMX Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "MMX Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "MMX Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags == 0, "MMX Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "MMX Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "MMX Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "MMX Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "MMX Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "MMX Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else + { + ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", device_desc, device_name); + if (hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hal line has pow2 set\n"); + else + trace("hal line does NOT have pow2 set\n"); + if (hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hal tri has pow2 set\n"); + else + trace("hal tri does NOT have pow2 set\n"); + if (hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hel line has pow2 set\n"); + else + trace("hel line does NOT have pow2 set\n"); + if (hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hel tri has pow2 set\n"); + else + trace("hel tri does NOT have pow2 set\n"); + } + + return DDENUMRET_OK; +} + +static void test_enum_devices(void) +{ + IDirectDraw *ddraw; + IDirect3D *d3d; + ULONG refcount; + HRESULT hr; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + + hr = IDirectDraw_QueryInterface(ddraw, &IID_IDirect3D, (void **)&d3d); + if (FAILED(hr)) + { + skip("D3D interface is not available, skipping test.\n"); + IDirectDraw_Release(ddraw); + return; + } + + hr = IDirect3D_EnumDevices(d3d, NULL, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr); + + hr = IDirect3D_EnumDevices(d3d, test_enum_devices_caps_callback, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + IDirect3D_Release(d3d); + refcount = IDirectDraw_Release(ddraw); + ok(!refcount, "Device has %lu references left.\n", refcount); +} + START_TEST(ddraw1) { DDDEVICEIDENTIFIER identifier; @@ -15263,4 +15471,5 @@ START_TEST(ddraw1) test_get_display_mode(); run_for_each_device_type(test_texture_wrong_caps); test_filling_convention(); + test_enum_devices(); } diff --git a/dlls/ddraw/tests/ddraw2.c b/dlls/ddraw/tests/ddraw2.c index 0aea1587156..d5b72793526 100644 --- a/dlls/ddraw/tests/ddraw2.c +++ b/dlls/ddraw/tests/ddraw2.c @@ -16091,6 +16091,214 @@ static void test_filling_convention(void) DestroyWindow(window); } +static HRESULT WINAPI test_enum_devices_caps_callback(GUID *guid, char *device_desc, + char *device_name, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx) +{ + if(IsEqualGUID(&IID_IDirect3DRGBDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "RGB Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "RGB Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "RGB Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "RGB Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "RGB Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "RGB Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags == 0, "RGB Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "RGB Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DHALDevice, guid)) + { + ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device hal caps has colormodel %lu\n", hel->dcmColorModel); + ok(hel->dcmColorModel == 0, "HAL Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags != 0, "HAL Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "HAL Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok(hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT, + "HAL Device hal device caps does not have D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok(hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX, + "HAL Device hal device caps does not have D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DRefDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "REF Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "REF Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "REF Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "REF Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "REF Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "REF Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "REF Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "REF Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "REF Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DRampDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "Ramp Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "Ramp Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "Ramp Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "Ramp Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "Ramp Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "Ramp Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device hel caps has colormodel %lu\n", + hel->dcmColorModel); + + ok(hal->dwFlags == 0, "Ramp Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "Ramp Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "Ramp Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "Ramp Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "Ramp Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "Ramp Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DMMXDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "MMX Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "MMX Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "MMX Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "MMX Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "MMX Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "MMX Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags == 0, "MMX Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "MMX Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "MMX Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "MMX Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "MMX Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "MMX Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else + { + ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", device_desc, device_name); + if (hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hal line has pow2 set\n"); + else + trace("hal line does NOT have pow2 set\n"); + if (hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hal tri has pow2 set\n"); + else + trace("hal tri does NOT have pow2 set\n"); + if (hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hel line has pow2 set\n"); + else + trace("hel line does NOT have pow2 set\n"); + if (hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hel tri has pow2 set\n"); + else + trace("hel tri does NOT have pow2 set\n"); + } + + return DDENUMRET_OK; +} + +static void test_enum_devices(void) +{ + IDirectDraw2 *ddraw; + IDirect3D2 *d3d; + ULONG refcount; + HRESULT hr; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + + hr = IDirectDraw2_QueryInterface(ddraw, &IID_IDirect3D2, (void **)&d3d); + if (FAILED(hr)) + { + skip("D3D interface is not available, skipping test.\n"); + IDirectDraw2_Release(ddraw); + return; + } + + hr = IDirect3D2_EnumDevices(d3d, NULL, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr); + + hr = IDirect3D2_EnumDevices(d3d, test_enum_devices_caps_callback, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + IDirect3D2_Release(d3d); + refcount = IDirectDraw2_Release(ddraw); + ok(!refcount, "Device has %lu references left.\n", refcount); +} + static void run_for_each_device_type(void (*test_func)(const GUID *)) { test_func(&IID_IDirect3DHALDevice); @@ -16221,4 +16429,5 @@ START_TEST(ddraw2) test_get_display_mode(); run_for_each_device_type(test_texture_wrong_caps); test_filling_convention(); + test_enum_devices(); } diff --git a/dlls/ddraw/tests/ddraw4.c b/dlls/ddraw/tests/ddraw4.c index ab37adc000a..471f6fc3f09 100644 --- a/dlls/ddraw/tests/ddraw4.c +++ b/dlls/ddraw/tests/ddraw4.c @@ -19160,6 +19160,214 @@ static void test_filling_convention(void) DestroyWindow(window); } +static HRESULT WINAPI test_enum_devices_caps_callback(GUID *guid, char *device_desc, + char *device_name, D3DDEVICEDESC *hal, D3DDEVICEDESC *hel, void *ctx) +{ + if(IsEqualGUID(&IID_IDirect3DRGBDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "RGB Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "RGB Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "RGB Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "RGB Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "RGB Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "RGB Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "RGB Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_RGB, "RGB Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags == 0, "RGB Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "RGB Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DHALDevice, guid)) + { + ok(hal->dcmColorModel == D3DCOLOR_RGB, "HAL Device hal caps has colormodel %lu\n", hel->dcmColorModel); + ok(hel->dcmColorModel == 0, "HAL Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags != 0, "HAL Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "HAL Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok(hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT, + "HAL Device hal device caps does not have D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok(hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX, + "HAL Device hal device caps does not have D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DRefDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "REF Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "REF Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "REF Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "REF Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "REF Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "REF Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "REF Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "REF Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "REF Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "REF Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DRampDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "Ramp Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "Ramp Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "Ramp Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "Ramp Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "Ramp Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "Ramp Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "Ramp Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_MONO, "Ramp Device hel caps has colormodel %lu\n", + hel->dcmColorModel); + + ok(hal->dwFlags == 0, "Ramp Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "Ramp Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "Ramp Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "Ramp Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "Ramp Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "Ramp Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if(IsEqualGUID(&IID_IDirect3DMMXDevice, guid)) + { + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "MMX Device hal line caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) == 0, + "MMX Device hal tri caps has D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "MMX Device hel line caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_POW2 flag set\n"); + + ok((hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "MMX Device hal line caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok((hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE) == 0, + "MMX Device hal tri caps has D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + ok(hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_PERSPECTIVE, + "MMX Device hel tri caps does not have D3DPTEXTURECAPS_PERSPECTIVE set\n"); + + ok(hal->dcmColorModel == 0, "MMX Device hal caps has colormodel %lu\n", hal->dcmColorModel); + ok(hel->dcmColorModel == D3DCOLOR_RGB, "MMX Device hel caps has colormodel %lu\n", hel->dcmColorModel); + + ok(hal->dwFlags == 0, "MMX Device hal caps has hardware flags %#lx\n", hal->dwFlags); + ok(hel->dwFlags != 0, "MMX Device hel caps has hardware flags %#lx\n", hel->dwFlags); + + ok((hal->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "MMX Device hal device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "MMX Device hel device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((hal->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "MMX Device hal device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + ok((hel->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "MMX Device hel device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else + { + ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", device_desc, device_name); + if (hal->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hal line has pow2 set\n"); + else + trace("hal line does NOT have pow2 set\n"); + if (hal->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hal tri has pow2 set\n"); + else + trace("hal tri does NOT have pow2 set\n"); + if (hel->dpcLineCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hel line has pow2 set\n"); + else + trace("hel line does NOT have pow2 set\n"); + if (hel->dpcTriCaps.dwTextureCaps & D3DPTEXTURECAPS_POW2) + trace("hel tri has pow2 set\n"); + else + trace("hel tri does NOT have pow2 set\n"); + } + + return DDENUMRET_OK; +} + +static void test_enum_devices(void) +{ + IDirectDraw4 *ddraw; + IDirect3D3 *d3d; + ULONG refcount; + HRESULT hr; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + + hr = IDirectDraw4_QueryInterface(ddraw, &IID_IDirect3D3, (void **)&d3d); + if (FAILED(hr)) + { + skip("D3D interface is not available, skipping test.\n"); + IDirectDraw4_Release(ddraw); + return; + } + + hr = IDirect3D3_EnumDevices(d3d, NULL, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr); + + hr = IDirect3D3_EnumDevices(d3d, test_enum_devices_caps_callback, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + IDirect3D3_Release(d3d); + refcount = IDirectDraw4_Release(ddraw); + ok(!refcount, "Device has %lu references left.\n", refcount); +} + START_TEST(ddraw4) { DDDEVICEIDENTIFIER identifier; @@ -19300,4 +19508,5 @@ START_TEST(ddraw4) test_get_display_mode(); run_for_each_device_type(test_texture_wrong_caps); test_filling_convention(); + test_enum_devices(); } diff --git a/dlls/ddraw/tests/ddraw7.c b/dlls/ddraw/tests/ddraw7.c index c72ea64c17d..15ab548ebc6 100644 --- a/dlls/ddraw/tests/ddraw7.c +++ b/dlls/ddraw/tests/ddraw7.c @@ -19390,6 +19390,67 @@ static void test_filling_convention(void) DestroyWindow(window); } +static HRESULT WINAPI test_enum_devices_caps_callback(char *device_desc, char *device_name, + D3DDEVICEDESC7 *device_desc7, void *ctx) +{ + if (IsEqualGUID(&device_desc7->deviceGUID, &IID_IDirect3DTnLHalDevice)) + { + ok(device_desc7->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT, + "TnLHal Device device caps does not have D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok(device_desc7->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX, + "TnLHal Device device caps does not have D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if (IsEqualGUID(&device_desc7->deviceGUID, &IID_IDirect3DHALDevice)) + { + ok((device_desc7->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "HAL Device device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok(device_desc7->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX, + "HAL Device device caps does not have D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else if (IsEqualGUID(&device_desc7->deviceGUID, &IID_IDirect3DRGBDevice)) + { + ok((device_desc7->dwDevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) == 0, + "RGB Device device caps has D3DDEVCAPS_HWTRANSFORMANDLIGHT set\n"); + ok((device_desc7->dwDevCaps & D3DDEVCAPS_DRAWPRIMITIVES2EX) == 0, + "RGB Device device caps has D3DDEVCAPS_DRAWPRIMITIVES2EX set\n"); + } + else + { + ok(FALSE, "Unexpected device enumerated: \"%s\" \"%s\"\n", device_desc, device_name); + } + + return DDENUMRET_OK; +} + +static void test_enum_devices(void) +{ + IDirectDraw7 *ddraw; + IDirect3D7 *d3d; + ULONG refcount; + HRESULT hr; + + ddraw = create_ddraw(); + ok(!!ddraw, "Failed to create a ddraw object.\n"); + + hr = IDirectDraw7_QueryInterface(ddraw, &IID_IDirect3D7, (void **)&d3d); + if (FAILED(hr)) + { + skip("D3D interface is not available, skipping test.\n"); + IDirectDraw7_Release(ddraw); + return; + } + + hr = IDirect3D7_EnumDevices(d3d, NULL, NULL); + ok(hr == DDERR_INVALIDPARAMS, "Got hr %#lx.\n", hr); + + hr = IDirect3D7_EnumDevices(d3d, test_enum_devices_caps_callback, NULL); + ok(hr == D3D_OK, "Got hr %#lx.\n", hr); + + IDirect3D7_Release(d3d); + refcount = IDirectDraw7_Release(ddraw); + ok(!refcount, "Device has %lu references left.\n", refcount); +} + static void run_for_each_device_type(void (*test_func)(const GUID *)) { test_func(hw_device_guid); @@ -19568,4 +19629,5 @@ START_TEST(ddraw7) test_get_display_mode(); run_for_each_device_type(test_texture_wrong_caps); test_filling_convention(); + test_enum_devices(); } diff --git a/dlls/msvcrt/concurrency.c b/dlls/msvcrt/concurrency.c index d0c9924c631..a1c5c635602 100644 --- a/dlls/msvcrt/concurrency.c +++ b/dlls/msvcrt/concurrency.c @@ -24,6 +24,8 @@ #include "windef.h" #include "winternl.h" #include "wine/debug.h" +#include "wine/exception.h" +#include "wine/list.h" #include "msvcrt.h" #include "cxx.h" @@ -135,6 +137,7 @@ typedef struct { int shutdown_size; HANDLE *shutdown_events; CRITICAL_SECTION cs; + struct list scheduled_chores; } ThreadScheduler; extern const vtable_ptr ThreadScheduler_vtable; @@ -164,15 +167,32 @@ typedef struct yield_func yield_func; } SpinWait; +#define FINISHED_INITIAL 0x80000000 typedef struct { - char dummy; -} _UnrealizedChore; + void *unk1; + unsigned int unk2; + void *unk3; + Context *context; + volatile LONG count; + volatile LONG finished; + void *exception; + void *event; +} _StructuredTaskCollection; -typedef struct +typedef struct _UnrealizedChore { - char dummy; -} _StructuredTaskCollection; + const vtable_ptr *vtable; + void (__cdecl *chore_proc)(struct _UnrealizedChore*); + _StructuredTaskCollection *task_collection; + void (__cdecl *chore_wrapper)(struct _UnrealizedChore*); + void *unk[6]; +} _UnrealizedChore; + +struct scheduled_chore { + struct list entry; + _UnrealizedChore *chore; +}; /* keep in sync with msvcp90/msvcp90.h */ typedef struct cs_queue @@ -629,6 +649,7 @@ DEFINE_RTTI_DATA1(scheduler_resource_allocation_error, 0, &cexception_rtti_base_ DEFINE_CXX_DATA1(improper_lock, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(improper_scheduler_attach, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(improper_scheduler_detach, &cexception_cxx_type_info, cexception_dtor) +DEFINE_CXX_DATA1(invalid_multiple_scheduling, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(invalid_scheduler_policy_key, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(invalid_scheduler_policy_thread_specification, &cexception_cxx_type_info, cexception_dtor) DEFINE_CXX_DATA1(invalid_scheduler_policy_value, &cexception_cxx_type_info, cexception_dtor) @@ -697,29 +718,38 @@ static Context* get_current_context(void) return ret; } +static Scheduler* get_scheduler_from_context(Context *ctx) +{ + ExternalContextBase *context = (ExternalContextBase*)ctx; + + if (context->context.vtable != &ExternalContextBase_vtable) + return NULL; + return context->scheduler.scheduler; +} + static Scheduler* try_get_current_scheduler(void) { - ExternalContextBase *context = (ExternalContextBase*)try_get_current_context(); + Context *context = try_get_current_context(); + Scheduler *ret; if (!context) return NULL; - if (context->context.vtable != &ExternalContextBase_vtable) { + ret = get_scheduler_from_context(context); + if (!ret) ERR("unknown context set\n"); - return NULL; - } - return context->scheduler.scheduler; + return ret; } static Scheduler* get_current_scheduler(void) { - ExternalContextBase *context = (ExternalContextBase*)get_current_context(); + Context *context = get_current_context(); + Scheduler *ret; - if (context->context.vtable != &ExternalContextBase_vtable) { + ret = get_scheduler_from_context(context); + if (!ret) ERR("unknown context set\n"); - return NULL; - } - return context->scheduler.scheduler; + return ret; } /* ?CurrentContext(a)Context@Concurrency@@SAPAV12(a)XZ */ @@ -830,6 +860,25 @@ bool __thiscall ExternalContextBase_IsSynchronouslyBlocked(const ExternalContext return FALSE; } +static void remove_scheduled_chores(Scheduler *scheduler, const ExternalContextBase *context) +{ + ThreadScheduler *tscheduler = (ThreadScheduler*)scheduler; + struct scheduled_chore *sc, *next; + + if (tscheduler->scheduler.vtable != &ThreadScheduler_vtable) + return; + + EnterCriticalSection(&tscheduler->cs); + LIST_FOR_EACH_ENTRY_SAFE(sc, next, &tscheduler->scheduled_chores, + struct scheduled_chore, entry) { + if (sc->chore->task_collection->context == &context->context) { + list_remove(&sc->entry); + operator_delete(sc); + } + } + LeaveCriticalSection(&tscheduler->cs); +} + static void ExternalContextBase_dtor(ExternalContextBase *this) { struct scheduler_list *scheduler_cur, *scheduler_next; @@ -845,10 +894,12 @@ static void ExternalContextBase_dtor(ExternalContextBase *this) } if (this->scheduler.scheduler) { + remove_scheduled_chores(this->scheduler.scheduler, this); call_Scheduler_Release(this->scheduler.scheduler); for(scheduler_cur=this->scheduler.next; scheduler_cur; scheduler_cur=scheduler_next) { scheduler_next = scheduler_cur->next; + remove_scheduled_chores(scheduler_cur->scheduler, this); call_Scheduler_Release(scheduler_cur->scheduler); operator_delete(scheduler_cur); } @@ -1148,6 +1199,7 @@ void __thiscall SchedulerPolicy_dtor(SchedulerPolicy *this) static void ThreadScheduler_dtor(ThreadScheduler *this) { int i; + struct scheduled_chore *sc, *next; if(this->ref != 0) WARN("ref = %ld\n", this->ref); SchedulerPolicy_dtor(&this->policy); @@ -1158,6 +1210,12 @@ static void ThreadScheduler_dtor(ThreadScheduler *this) this->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&this->cs); + + if (!list_empty(&this->scheduled_chores)) + ERR("scheduled chore list is not empty\n"); + LIST_FOR_EACH_ENTRY_SAFE(sc, next, &this->scheduled_chores, + struct scheduled_chore, entry) + operator_delete(sc); } DEFINE_THISCALL_WRAPPER(ThreadScheduler_Id, 4) @@ -1271,15 +1329,29 @@ typedef struct { void (__cdecl *proc)(void*); void *data; + ThreadScheduler *scheduler; } schedule_task_arg; +void __cdecl CurrentScheduler_Detach(void); + static void WINAPI schedule_task_proc(PTP_CALLBACK_INSTANCE instance, void *context, PTP_WORK work) { schedule_task_arg arg; + BOOL detach = FALSE; arg = *(schedule_task_arg*)context; operator_delete(context); + + if(&arg.scheduler->scheduler != try_get_current_scheduler()) { + ThreadScheduler_Attach(arg.scheduler); + detach = TRUE; + } + ThreadScheduler_Release(arg.scheduler); + arg.proc(arg.data); + + if(detach) + CurrentScheduler_Detach(); } DEFINE_THISCALL_WRAPPER(ThreadScheduler_ScheduleTask_loc, 16) @@ -1294,11 +1366,14 @@ void __thiscall ThreadScheduler_ScheduleTask_loc(ThreadScheduler *this, arg = operator_new(sizeof(*arg)); arg->proc = proc; arg->data = data; + arg->scheduler = this; + ThreadScheduler_Reference(this); work = CreateThreadpoolWork(schedule_task_proc, arg, NULL); if(!work) { scheduler_resource_allocation_error e; + ThreadScheduler_Release(this); operator_delete(arg); scheduler_resource_allocation_error_ctor_name(&e, NULL, HRESULT_FROM_WIN32(GetLastError())); @@ -1366,6 +1441,8 @@ static ThreadScheduler* ThreadScheduler_ctor(ThreadScheduler *this, InitializeCriticalSection(&this->cs); this->cs.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": ThreadScheduler"); + + list_init(&this->scheduled_chores); return this; } @@ -1815,6 +1892,114 @@ void __thiscall _StructuredTaskCollection_dtor(_StructuredTaskCollection *this) #endif /* _MSVCR_VER >= 120 */ +static ThreadScheduler *get_thread_scheduler_from_context(Context *context) +{ + Scheduler *scheduler = get_scheduler_from_context(context); + if (scheduler && scheduler->vtable == &ThreadScheduler_vtable) + return (ThreadScheduler*)scheduler; + return NULL; +} + +static void CALLBACK chore_wrapper_finally(BOOL normal, void *data) +{ + _UnrealizedChore *chore = data; + LONG prev_finished, new_finished; + volatile LONG *ptr; + + TRACE("(%u %p)\n", normal, data); + + if (!chore->task_collection) + return; + ptr = &chore->task_collection->finished; + chore->task_collection = NULL; + + do { + prev_finished = *ptr; + if (prev_finished == FINISHED_INITIAL) + new_finished = 1; + else + new_finished = prev_finished + 1; + } while (InterlockedCompareExchange(ptr, new_finished, prev_finished) + != prev_finished); +} + +static void __cdecl chore_wrapper(_UnrealizedChore *chore) +{ + TRACE("(%p)\n", chore); + + __TRY + { + if (chore->chore_proc) + chore->chore_proc(chore); + } + __FINALLY_CTX(chore_wrapper_finally, chore) +} + +static void __cdecl _StructuredTaskCollection_scheduler_cb(void *data) +{ + ThreadScheduler *scheduler = (ThreadScheduler*)get_current_scheduler(); + struct list *entry; + struct scheduled_chore *sc; + _UnrealizedChore *chore; + + TRACE("(%p)\n", scheduler); + + if (scheduler->scheduler.vtable != &ThreadScheduler_vtable) + { + ERR("unknown scheduler set\n"); + return; + } + + EnterCriticalSection(&scheduler->cs); + entry = list_head(&scheduler->scheduled_chores); + if (entry) + list_remove(entry); + LeaveCriticalSection(&scheduler->cs); + if (!entry) + return; + + sc = LIST_ENTRY(entry, struct scheduled_chore, entry); + chore = sc->chore; + operator_delete(sc); + + chore->chore_wrapper(chore); +} + +static bool schedule_chore(_StructuredTaskCollection *this, + _UnrealizedChore *chore, Scheduler **pscheduler) +{ + struct scheduled_chore *sc; + ThreadScheduler *scheduler; + + if (chore->task_collection) { + invalid_multiple_scheduling e; + invalid_multiple_scheduling_ctor_str(&e, "Chore scheduled multiple times"); + _CxxThrowException(&e, &invalid_multiple_scheduling_exception_type); + return FALSE; + } + + if (!this->context) + this->context = get_current_context(); + scheduler = get_thread_scheduler_from_context(this->context); + if (!scheduler) { + ERR("unknown context or scheduler set\n"); + return FALSE; + } + + sc = operator_new(sizeof(*sc)); + sc->chore = chore; + + chore->task_collection = this; + chore->chore_wrapper = chore_wrapper; + InterlockedIncrement(&this->count); + + EnterCriticalSection(&scheduler->cs); + list_add_head(&scheduler->scheduled_chores, &sc->entry); + LeaveCriticalSection(&scheduler->cs); + *pscheduler = &scheduler->scheduler; + return TRUE; +} + #if _MSVCR_VER >= 110 /* ?_Schedule(a)_StructuredTaskCollection@details(a)Concurrency@@QAAXPAV_UnrealizedChore(a)23@PAVlocation(a)3@@Z */ @@ -1825,7 +2010,15 @@ void __thiscall _StructuredTaskCollection__Schedule_loc( _StructuredTaskCollection *this, _UnrealizedChore *chore, /*location*/void *placement) { - FIXME("(%p %p %p): stub!\n", this, chore, placement); + Scheduler *scheduler; + + TRACE("(%p %p %p)\n", this, chore, placement); + + if (schedule_chore(this, chore, &scheduler)) + { + call_Scheduler_ScheduleTask_loc(scheduler, + _StructuredTaskCollection_scheduler_cb, NULL, placement); + } } #endif /* _MSVCR_VER >= 110 */ @@ -1837,7 +2030,15 @@ DEFINE_THISCALL_WRAPPER(_StructuredTaskCollection__Schedule, 8) void __thiscall _StructuredTaskCollection__Schedule( _StructuredTaskCollection *this, _UnrealizedChore *chore) { - FIXME("(%p %p): stub!\n", this, chore); + Scheduler *scheduler; + + TRACE("(%p %p)\n", this, chore); + + if (schedule_chore(this, chore, &scheduler)) + { + call_Scheduler_ScheduleTask(scheduler, + _StructuredTaskCollection_scheduler_cb, NULL); + } } /* ?_RunAndWait(a)_StructuredTaskCollection@details(a)Concurrency@@QAA?AW4_TaskCollectionStatus(a)23@PAV_UnrealizedChore(a)23@@Z */ @@ -3096,6 +3297,7 @@ void msvcrt_init_concurrency(void *base) init_improper_lock_cxx(base); init_improper_scheduler_attach_cxx(base); init_improper_scheduler_detach_cxx(base); + init_invalid_multiple_scheduling_cxx(base); init_invalid_scheduler_policy_key_cxx(base); init_invalid_scheduler_policy_thread_specification_cxx(base); init_invalid_scheduler_policy_value_cxx(base); diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c index 8f1aa4d45a3..85d48cef7aa 100644 --- a/dlls/ntoskrnl.exe/instr.c +++ b/dlls/ntoskrnl.exe/instr.c @@ -890,7 +890,50 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) } break; /* Unable to emulate it */ } + case 0x38: + case 0x39: /* cmp r/m r/m */ + { + ULONG64 *data = (ULONG64*)INSTR_GetOperandAddr(context, instr + 1, prefixlen + 1, long_addr, rex, segprefix, &len); + ULONG64 *data2 = (ULONG64*)INSTR_GetOperandAddr(context, instr + 2, prefixlen + 2, long_addr, rex, segprefix, &len); + SIZE_T offset = (BYTE*)data - user_shared_data; + SIZE_T offset2 = (BYTE*)data2 - user_shared_data; + SIZE_T data_size = get_op_size(long_op, rex); + BOOL is_user_shared_data = FALSE; + ULONG64 cmp1, cmp2, bitmask; + if(offset <= KSHARED_USER_DATA_PAGE_SIZE - data_size) + { + TRACE("USD offset %#x at %p\n",(unsigned int) offset, (void*) context->Rip); + data = (ULONG64*)(wine_user_shared_data + offset); + is_user_shared_data = TRUE; + } + if(offset2 <= KSHARED_USER_DATA_PAGE_SIZE - data_size) + { + TRACE("USD offset %#x at %p\n", (unsigned int) offset2, (void*) context->Rip); + data2 = (ULONG64*)(wine_user_shared_data + offset2); + is_user_shared_data = TRUE; + } + if(is_user_shared_data) + { + /* clear ZF and CF */ + context->EFlags &= ~(1UL << 6); + context->EFlags &= ~(1UL); + + bitmask = ((1ULL << (8 * data_size)) - 1); + /* FIXME("bitmask %llx\n", bitmask); */ + cmp1 = (*data) & bitmask; + cmp2 = (*data2) & bitmask; + + if(cmp1 == cmp2) + context->EFlags |= (1UL << 6); /* ZF */ + else if(cmp1 < cmp2) + context->EFlags |= 1UL; /* CF */ + + context->Rip += prefixlen + len + 1; + return ExceptionContinueExecution; + } + break; + } case 0xa0: /* mov Ob, AL */ case 0xa1: /* mov Ovqp, rAX */ { diff --git a/dlls/qasf/tests/asfreader.c b/dlls/qasf/tests/asfreader.c index 3a2e18a3054..fcc82a23c29 100644 --- a/dlls/qasf/tests/asfreader.c +++ b/dlls/qasf/tests/asfreader.c @@ -513,6 +513,475 @@ static void test_filesourcefilter(void) ok(!ref, "Got outstanding refcount %ld.\n", ref); } +static void test_filter_state(void) +{ + const WCHAR *filename = load_resource(L"test.wmv"); + IBaseFilter *filter = create_asf_reader(); + IFileSourceFilter *file_source; + IReferenceClock *clock; + IEnumPins *enum_pins; + IFilterGraph *graph; + FILTER_STATE state; + IPin *pins[4]; + HRESULT hr; + ULONG ref; + + hr = IBaseFilter_QueryInterface(filter, &IID_IFileSourceFilter, (void **)&file_source); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFileSourceFilter_Load(file_source, filename, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IFileSourceFilter_Release(file_source); + + hr = IBaseFilter_EnumPins(filter, &enum_pins); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumPins_Next(enum_pins, 1, pins, NULL); + todo_wine + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + if (hr == S_OK) + IPin_Release(pins[0]); + IEnumPins_Release(enum_pins); + + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(state == State_Stopped, "Got state %#x.\n", state); + + hr = IBaseFilter_Run(filter, GetTickCount() * 10000); + todo_wine + ok(hr == E_FAIL, "Got hr %#lx.\n", hr); + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine + ok(state == State_Stopped, "Got state %#x.\n", state); + hr = IBaseFilter_Pause(filter); + todo_wine + ok(hr == E_FAIL, "Got hr %#lx.\n", hr); + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + todo_wine + ok(state == State_Stopped, "Got state %#x.\n", state); + hr = IBaseFilter_Stop(filter); + todo_wine + ok(hr == E_FAIL, "Got hr %#lx.\n", hr); + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(state == State_Stopped, "Got state %#x.\n", state); + + hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, + &IID_IFilterGraph, (void **)&graph); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFilterGraph_AddFilter(graph, filter, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ref = IFilterGraph_Release(graph); + ok(!ref, "Got ref %ld.\n", ref); + + hr = IBaseFilter_EnumPins(filter, &enum_pins); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IEnumPins_Next(enum_pins, 1, pins, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IPin_Release(pins[0]); + hr = IEnumPins_Next(enum_pins, 1, pins, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IPin_Release(pins[0]); + hr = IEnumPins_Next(enum_pins, 1, pins, NULL); + ok(hr == S_FALSE, "Got hr %#lx.\n", hr); + IEnumPins_Release(enum_pins); + + hr = IBaseFilter_GetSyncSource(filter, &clock); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(!clock, "Got clock %p.\n", clock); + + hr = IBaseFilter_Run(filter, GetTickCount() * 10000); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(state == State_Running, "Got state %#x.\n", state); + + hr = IBaseFilter_Stop(filter); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(state == State_Stopped, "Got state %#x.\n", state); + + ref = IBaseFilter_Release(filter); + ok(!ref, "Got ref %ld.\n", ref); +} + +struct test_sink +{ + struct strmbase_sink sink; + + DWORD receive_tid; + HANDLE receive_event; + BOOL receive_can_block; + IMemAllocator *allocator; +}; + +static inline struct test_sink *impl_from_IMemInputPin(IMemInputPin *iface) +{ + return CONTAINING_RECORD(iface, struct test_sink, sink.IMemInputPin_iface); +} + +static HRESULT WINAPI test_mem_input_pin_QueryInterface(IMemInputPin *iface, REFIID iid, void **out) +{ + struct test_sink *pin = impl_from_IMemInputPin(iface); + return IPin_QueryInterface(&pin->sink.pin.IPin_iface, iid, out); +} + +static ULONG WINAPI test_mem_input_pin_AddRef(IMemInputPin *iface) +{ + struct test_sink *pin = impl_from_IMemInputPin(iface); + return IPin_AddRef(&pin->sink.pin.IPin_iface); +} + +static ULONG WINAPI test_mem_input_pin_Release(IMemInputPin *iface) +{ + struct test_sink *pin = impl_from_IMemInputPin(iface); + return IPin_Release(&pin->sink.pin.IPin_iface); +} + +static HRESULT WINAPI test_mem_input_pin_GetAllocator(IMemInputPin *iface, + IMemAllocator **allocator) +{ + struct test_sink *pin = impl_from_IMemInputPin(iface); + if (!pin->allocator) + return VFW_E_NO_ALLOCATOR; + IMemAllocator_AddRef((*allocator = pin->allocator)); + return S_OK; +} + +static HRESULT WINAPI test_mem_input_pin_NotifyAllocator(IMemInputPin *iface, + IMemAllocator *allocator, BOOL read_only) +{ + struct test_sink *pin = impl_from_IMemInputPin(iface); + IMemAllocator_AddRef((pin->allocator = allocator)); + return S_OK; +} + +static HRESULT WINAPI test_mem_input_pin_GetAllocatorRequirements(IMemInputPin *iface, + ALLOCATOR_PROPERTIES *props) +{ + memset(props, 0, sizeof(*props)); + return S_OK; +} + +static HRESULT WINAPI test_mem_input_pin_Receive(IMemInputPin *iface, + IMediaSample *sample) +{ + struct test_sink *pin = impl_from_IMemInputPin(iface); + + pin->receive_tid = GetCurrentThreadId(); + SetEvent(pin->receive_event); + + todo_wine + ok(0, "Unexpected call.\n"); + + return S_OK; +} + +static HRESULT WINAPI test_mem_input_pin_ReceiveMultiple(IMemInputPin *iface, + IMediaSample **samples, LONG count, LONG *processed) +{ + struct test_sink *pin = impl_from_IMemInputPin(iface); + + pin->receive_tid = GetCurrentThreadId(); + SetEvent(pin->receive_event); + + *processed = count; + return S_OK; +} + +static HRESULT WINAPI test_mem_input_pin_ReceiveCanBlock(IMemInputPin *iface) +{ + struct test_sink *pin = impl_from_IMemInputPin(iface); + return pin->receive_can_block ? S_OK : S_FALSE; +} + +static const IMemInputPinVtbl test_mem_input_pin_vtbl = +{ + test_mem_input_pin_QueryInterface, + test_mem_input_pin_AddRef, + test_mem_input_pin_Release, + test_mem_input_pin_GetAllocator, + test_mem_input_pin_NotifyAllocator, + test_mem_input_pin_GetAllocatorRequirements, + test_mem_input_pin_Receive, + test_mem_input_pin_ReceiveMultiple, + test_mem_input_pin_ReceiveCanBlock, +}; + +struct test_filter +{ + struct strmbase_filter filter; + struct test_sink video; + struct test_sink audio; +}; + +static inline struct test_filter *impl_from_strmbase_filter(struct strmbase_filter *iface) +{ + return CONTAINING_RECORD(iface, struct test_filter, filter); +} + +static inline struct strmbase_sink *impl_from_strmbase_pin(struct strmbase_pin *iface) +{ + return CONTAINING_RECORD(iface, struct strmbase_sink, pin); +} + +static struct strmbase_pin *test_filter_get_pin(struct strmbase_filter *iface, unsigned int index) +{ + struct test_filter *filter = impl_from_strmbase_filter(iface); + if (index == 0) + return &filter->video.sink.pin; + if (index == 1) + return &filter->audio.sink.pin; + return NULL; +} + +static void test_filter_destroy(struct strmbase_filter *iface) +{ + struct test_filter *filter = impl_from_strmbase_filter(iface); + strmbase_sink_cleanup(&filter->audio.sink); + strmbase_sink_cleanup(&filter->video.sink); + strmbase_filter_cleanup(&filter->filter); +} + +static const struct strmbase_filter_ops test_filter_ops = +{ + .filter_get_pin = test_filter_get_pin, + .filter_destroy = test_filter_destroy, +}; + +static HRESULT test_sink_query_interface(struct strmbase_pin *iface, REFIID iid, void **out) +{ + struct strmbase_sink *sink = impl_from_strmbase_pin(iface); + + if (IsEqualGUID(iid, &IID_IMemInputPin)) + *out = &sink->IMemInputPin_iface; + else + return E_NOINTERFACE; + + IUnknown_AddRef((IUnknown *)*out); + return S_OK; +} + +static const struct strmbase_sink_ops test_sink_ops = +{ + .base.pin_query_interface = test_sink_query_interface, +}; + +static void test_filter_init(struct test_filter *filter) +{ + static const GUID clsid = {0xabacab}; + memset(filter, 0, sizeof(*filter)); + strmbase_filter_init(&filter->filter, NULL, &clsid, &test_filter_ops); + strmbase_sink_init(&filter->video.sink, &filter->filter, L"Video", &test_sink_ops, NULL); + filter->video.sink.IMemInputPin_iface.lpVtbl = &test_mem_input_pin_vtbl; + strmbase_sink_init(&filter->audio.sink, &filter->filter, L"Audio", &test_sink_ops, NULL); + filter->audio.sink.IMemInputPin_iface.lpVtbl = &test_mem_input_pin_vtbl; +} + +static void test_threading(BOOL receive_can_block) +{ + static const WAVEFORMATEX pcm_format = + { + .wFormatTag = WAVE_FORMAT_MSAUDIO1, + .nChannels = 1, + .nSamplesPerSec = 44100, + .nBlockAlign = 2, + .nAvgBytesPerSec = 88200, + .wBitsPerSample = 16, + .cbSize = 0, + }; + static const VIDEOINFOHEADER nv12_info = + { + .rcSource = {0, 0, 64, 48}, + .rcTarget = {0, 0, 64, 48}, + .bmiHeader = + { + .biSize = sizeof(BITMAPINFOHEADER), + .biWidth = 64, + .biHeight = 48, + .biPlanes = 1, + .biBitCount = 12, + .biCompression = MAKEFOURCC('N','V','1','2'), + .biSizeImage = 64 * 48 * 3 / 2, + }, + }; + static const MSAUDIO1WAVEFORMAT msaudio1_format = + { + .wfx.wFormatTag = WAVE_FORMAT_MSAUDIO1, + .wfx.nChannels = 1, + .wfx.nSamplesPerSec = 44100, + .wfx.nBlockAlign = 743, + .wfx.nAvgBytesPerSec = 16000, + .wfx.wBitsPerSample = 16, + .wfx.cbSize = sizeof(MSAUDIO1WAVEFORMAT) - sizeof(WAVEFORMATEX), + .wEncodeOptions = 1, + }; + static const VIDEOINFOHEADER2 wmv1_info2 = + { + .rcSource = {0, 0, 64, 48}, + .rcTarget = {0, 0, 64, 48}, + .dwBitRate = 189464, + .dwPictAspectRatioX = 64, + .dwPictAspectRatioY = 48, + .bmiHeader = + { + .biSize = sizeof(BITMAPINFOHEADER), + .biWidth = 64, + .biHeight = 48, + .biPlanes = 1, + .biBitCount = 24, + .biCompression = MAKEFOURCC('W','M','V','1'), + .biSizeImage = 64 * 48 * 3, + }, + }; + AM_MEDIA_TYPE audio_mt = + { + .majortype = MEDIATYPE_Audio, + .subtype = MEDIASUBTYPE_MSAUDIO1, + .bFixedSizeSamples = TRUE, + .lSampleSize = 743, + .formattype = FORMAT_WaveFormatEx, + .cbFormat = sizeof(MSAUDIO1WAVEFORMAT), + .pbFormat = (BYTE *)&msaudio1_format, + }; + AM_MEDIA_TYPE video_mt = + { + .majortype = MEDIATYPE_Video, + .subtype = WMMEDIASUBTYPE_WMV1, + .formattype = FORMAT_VideoInfo2, + .bTemporalCompression = TRUE, + .cbFormat = sizeof(VIDEOINFOHEADER2), + .pbFormat = (BYTE *)&wmv1_info2, + }; + AM_MEDIA_TYPE wine_audio_mt = + { + .majortype = MEDIATYPE_Audio, + .subtype = MEDIASUBTYPE_PCM, + .bFixedSizeSamples = TRUE, + .formattype = FORMAT_WaveFormatEx, + .cbFormat = sizeof(WAVEFORMATEX), + .pbFormat = (BYTE *)&pcm_format, + }; + AM_MEDIA_TYPE wine_video_mt = + { + .majortype = MEDIATYPE_Video, + .subtype = MEDIASUBTYPE_NV12, + .formattype = FORMAT_VideoInfo, + .bTemporalCompression = TRUE, + .cbFormat = sizeof(VIDEOINFOHEADER), + .pbFormat = (BYTE *)&nv12_info, + }; + + const WCHAR *filename = load_resource(L"test.wmv"); + IBaseFilter *filter = create_asf_reader(); + IFileSourceFilter *file_source; + struct test_filter test_sink; + IFilterGraph *graph; + FILTER_STATE state; + HRESULT hr; + IPin *pin; + DWORD ret; + ULONG ref; + + winetest_push_context("blocking %u", !!receive_can_block); + + test_filter_init(&test_sink); + + test_sink.video.receive_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!test_sink.video.receive_event, "CreateEventW failed, error %lu\n", GetLastError()); + test_sink.audio.receive_event = CreateEventW(NULL, FALSE, FALSE, NULL); + ok(!!test_sink.audio.receive_event, "CreateEventW failed, error %lu\n", GetLastError()); + + test_sink.video.receive_can_block = receive_can_block; + test_sink.audio.receive_can_block = receive_can_block; + + hr = IBaseFilter_QueryInterface(filter, &IID_IFileSourceFilter, (void **)&file_source); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFileSourceFilter_Load(file_source, filename, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IFileSourceFilter_Release(file_source); + + hr = CoCreateInstance(&CLSID_FilterGraph, NULL, CLSCTX_INPROC_SERVER, + &IID_IFilterGraph, (void **)&graph); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IFilterGraph_AddFilter(graph, filter, NULL); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + IFilterGraph_Release(graph); + + hr = IBaseFilter_FindPin(filter, L"Raw Video 0", &pin); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IPin_Connect(pin, &test_sink.video.sink.pin.IPin_iface, &video_mt); + todo_wine + ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr != S_OK) + { + hr = IPin_Connect(pin, &test_sink.video.sink.pin.IPin_iface, &wine_video_mt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + } + IPin_Release(pin); + + hr = IBaseFilter_FindPin(filter, L"Raw Audio 1", &pin); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IPin_Connect(pin, &test_sink.audio.sink.pin.IPin_iface, &audio_mt); + todo_wine + ok(hr == S_OK, "Got hr %#lx.\n", hr); + if (hr != S_OK) + { + hr = IPin_Connect(pin, &test_sink.audio.sink.pin.IPin_iface, &wine_audio_mt); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + } + IPin_Release(pin); + + hr = IBaseFilter_Run(filter, GetTickCount() * 10000); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(state == State_Running, "Got state %#x.\n", state); + + ret = WaitForSingleObject(test_sink.video.receive_event, 500); + ok(!ret, "Wait timed out.\n"); + ret = WaitForSingleObject(test_sink.audio.receive_event, 500); + ok(!ret, "Wait timed out.\n"); + + ok(test_sink.video.receive_tid != GetCurrentThreadId(), "got wrong thread\n"); + ok(test_sink.audio.receive_tid != GetCurrentThreadId(), "got wrong thread\n"); + if (receive_can_block) + { + todo_wine + ok(test_sink.audio.receive_tid != test_sink.video.receive_tid, "got wrong thread\n"); + } + else + ok(test_sink.audio.receive_tid == test_sink.video.receive_tid, "got wrong thread\n"); + + hr = IBaseFilter_Stop(filter); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IBaseFilter_GetState(filter, 0, &state); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + ok(state == State_Stopped, "Got state %#x.\n", state); + + hr = IPin_Disconnect(&test_sink.video.sink.pin.IPin_iface); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + hr = IPin_Disconnect(&test_sink.audio.sink.pin.IPin_iface); + ok(hr == S_OK, "Got hr %#lx.\n", hr); + + ref = IBaseFilter_Release(filter); + ok(!ref, "Got ref %ld.\n", ref); + + if (test_sink.video.allocator) + IMemAllocator_Release(test_sink.video.allocator); + if (test_sink.audio.allocator) + IMemAllocator_Release(test_sink.audio.allocator); + + CloseHandle(test_sink.video.receive_event); + CloseHandle(test_sink.audio.receive_event); + + ref = IBaseFilter_Release(&test_sink.filter.IBaseFilter_iface); + ok(!ref, "Got outstanding refcount %ld.\n", ref); + + winetest_pop_context(); +} + START_TEST(asfreader) { CoInitializeEx(NULL, COINIT_MULTITHREADED); @@ -520,6 +989,9 @@ START_TEST(asfreader) test_interfaces(); test_aggregation(); test_filesourcefilter(); + test_filter_state(); + test_threading(FALSE); + test_threading(TRUE); CoUninitialize(); } diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c index 446354fb9a5..78aad939198 100644 --- a/dlls/winepulse.drv/mmdevdrv.c +++ b/dlls/winepulse.drv/mmdevdrv.c @@ -2,6 +2,7 @@ * Copyright 2011-2012 Maarten Lankhorst * Copyright 2010-2011 Maarten Lankhorst for CodeWeavers * Copyright 2011 Andrew Eikum for CodeWeavers + * Copyright 2022 Huw Davies * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -28,6 +29,7 @@ #include "winternl.h" #include "wine/debug.h" #include "wine/list.h" +#include "wine/unixlib.h" #include "ole2.h" #include "mimeole.h" @@ -44,12 +46,14 @@ #include "endpointvolume.h" #include "audiopolicy.h" -#include "unixlib.h" +#include "../mmdevapi/unixlib.h" WINE_DEFAULT_DEBUG_CHANNEL(pulse); static unixlib_handle_t pulse_handle; +#define MAX_PULSE_NAME_LEN 256 + #define NULL_PTR_ERR MAKE_HRESULT(SEVERITY_ERROR, FACILITY_WIN32, RPC_X_NULL_REF_POINTER) /* From <dlls/mmdevapi/mmdevapi.h> */ @@ -229,8 +233,8 @@ static void pulse_call(enum unix_funcs code, void *params) static void pulse_release_stream(stream_handle stream, HANDLE timer) { struct release_stream_params params; - params.stream = stream; - params.timer = timer; + params.stream = stream; + params.timer_thread = timer; pulse_call(release_stream, ¶ms); } @@ -456,7 +460,7 @@ HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids_out, GUID **ke for (i = 0; i < params.num; i++) { WCHAR *name = (WCHAR *)((char *)params.endpoints + params.endpoints[i].name); - char *pulse_name = (char *)params.endpoints + params.endpoints[i].pulse_name; + char *pulse_name = (char *)params.endpoints + params.endpoints[i].device; unsigned int size = (wcslen(name) + 1) * sizeof(WCHAR); if (!(ids[i] = HeapAlloc(GetProcessHeap(), 0, size))) { @@ -875,11 +879,12 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface, } params.name = name = get_application_name(TRUE); - params.pulse_name = This->pulse_name; - params.dataflow = This->dataflow; - params.mode = mode; + params.device = This->pulse_name; + params.flow = This->dataflow; + params.share = mode; params.flags = flags; params.duration = duration; + params.period = period; params.fmt = fmt; params.stream = &stream; params.channel_count = &channel_count; @@ -1141,7 +1146,7 @@ static HRESULT WINAPI AudioClient_GetMixFormat(IAudioClient3 *iface, return E_POINTER; *pwfx = NULL; - params.pulse_name = This->pulse_name; + params.device = This->pulse_name; params.flow = This->dataflow; params.fmt = CoTaskMemAlloc(sizeof(WAVEFORMATEXTENSIBLE)); if (!params.fmt) @@ -1171,7 +1176,7 @@ static HRESULT WINAPI AudioClient_GetDevicePeriod(IAudioClient3 *iface, return E_POINTER; params.flow = This->dataflow; - params.pulse_name = This->pulse_name; + params.device = This->pulse_name; params.def_period = defperiod; params.min_period = minperiod; @@ -1562,7 +1567,7 @@ static HRESULT WINAPI AudioCaptureClient_GetBuffer(IAudioCaptureClient *iface, params.stream = This->pulse_stream; params.data = data; params.frames = frames; - params.flags = flags; + params.flags = (UINT*)flags; params.devpos = devpos; params.qpcpos = qpcpos; pulse_call(get_capture_buffer, ¶ms); @@ -2020,7 +2025,7 @@ static HRESULT WINAPI AudioSessionControl_GetState(IAudioSessionControl2 *iface, params.stream = client->pulse_stream; pulse_call(is_started, ¶ms); - if (params.started) { + if (params.result == S_OK) { *state = AudioSessionStateActive; goto out; } @@ -2659,35 +2664,33 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI { struct get_prop_value_params params; char pulse_name[MAX_PULSE_NAME_LEN]; - DWORD size; + unsigned int size = 0; TRACE("%s, (%s,%lu), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out); if (!get_pulse_name_by_guid(guid, pulse_name, ¶ms.flow)) return E_FAIL; - params.pulse_name = pulse_name; + params.device = pulse_name; params.guid = guid; params.prop = prop; - pulse_call(get_prop_value, ¶ms); + params.value = out; + params.buffer = NULL; + params.buffer_size = &size; + + while(1) { + pulse_call(get_prop_value, ¶ms); - if (params.result != S_OK) - return params.result; + if(params.result != E_NOT_SUFFICIENT_BUFFER) + break; - switch (params.vt) { - case VT_LPWSTR: - size = (wcslen(params.wstr) + 1) * sizeof(WCHAR); - if (!(out->pwszVal = CoTaskMemAlloc(size))) + CoTaskMemFree(params.buffer); + params.buffer = CoTaskMemAlloc(*params.buffer_size); + if(!params.buffer) return E_OUTOFMEMORY; - memcpy(out->pwszVal, params.wstr, size); - break; - case VT_UI4: - out->ulVal = params.ulVal; - break; - default: - assert(0); } - out->vt = params.vt; + if(FAILED(params.result)) + CoTaskMemFree(params.buffer); - return S_OK; + return params.result; } diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c index bd918b6f260..463f4c28d00 100644 --- a/dlls/winepulse.drv/pulse.c +++ b/dlls/winepulse.drv/pulse.c @@ -2,6 +2,7 @@ * Copyright 2011-2012 Maarten Lankhorst * Copyright 2010-2011 Maarten Lankhorst for CodeWeavers * Copyright 2011 Andrew Eikum for CodeWeavers + * Copyright 2022 Huw Davies * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -37,12 +38,20 @@ #include "initguid.h" #include "audioclient.h" -#include "unixlib.h" - #include "wine/debug.h" +#include "wine/list.h" +#include "wine/unixlib.h" + +#include "../mmdevapi/unixlib.h" WINE_DEFAULT_DEBUG_CHANNEL(pulse); +enum phys_device_bus_type { + phys_device_bus_invalid = -1, + phys_device_bus_pci, + phys_device_bus_usb +}; + struct pulse_stream { EDataFlow dataflow; @@ -268,7 +277,7 @@ static NTSTATUS pulse_get_endpoint_ids(void *args) endpoint->name = offset; memcpy((char *)params->endpoints + offset, dev->name, name_len * sizeof(WCHAR)); offset += name_len * sizeof(WCHAR); - endpoint->pulse_name = offset; + endpoint->device = offset; memcpy((char *)params->endpoints + offset, dev->pulse_name, len); offset += (len + 1) & ~1; endpoint++; @@ -1108,7 +1117,7 @@ static NTSTATUS pulse_create_stream(void *args) return STATUS_SUCCESS; } - stream->dataflow = params->dataflow; + stream->dataflow = params->flow; for (i = 0; i < ARRAY_SIZE(stream->vol); ++i) stream->vol[i] = 1.f; @@ -1119,7 +1128,7 @@ static NTSTATUS pulse_create_stream(void *args) goto exit; period = 0; - hr = get_device_period_helper(params->dataflow, params->pulse_name, &period, NULL); + hr = get_device_period_helper(params->flow, params->device, &period, NULL); if (FAILED(hr)) goto exit; @@ -1134,9 +1143,9 @@ static NTSTATUS pulse_create_stream(void *args) bufsize_bytes = stream->bufsize_frames * pa_frame_size(&stream->ss); stream->mmdev_period_usec = period / 10; - stream->share = params->mode; + stream->share = params->share; stream->flags = params->flags; - hr = pulse_stream_connect(stream, params->pulse_name, stream->period_bytes); + hr = pulse_stream_connect(stream, params->device, stream->period_bytes); if (SUCCEEDED(hr)) { UINT32 unalign; const pa_buffer_attr *attr = pa_stream_get_buffer_attr(stream->stream); @@ -1203,10 +1212,10 @@ static NTSTATUS pulse_release_stream(void *args) struct pulse_stream *stream = handle_get_stream(params->stream); SIZE_T size; - if(params->timer) { + if(params->timer_thread) { stream->please_quit = TRUE; - NtWaitForSingleObject(params->timer, FALSE, NULL); - NtClose(params->timer); + NtWaitForSingleObject(params->timer_thread, FALSE, NULL); + NtClose(params->timer_thread); } pulse_lock(); @@ -2055,7 +2064,7 @@ static NTSTATUS pulse_get_mix_format(void *args) PhysDevice *dev; LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) { - if (strcmp(params->pulse_name, dev->pulse_name)) + if (strcmp(params->device, dev->pulse_name)) continue; *params->fmt = dev->fmt; @@ -2072,7 +2081,7 @@ static NTSTATUS pulse_get_device_period(void *args) { struct get_device_period_params *params = args; - params->result = get_device_period_helper(params->flow, params->pulse_name, params->def_period, params->min_period); + params->result = get_device_period_helper(params->flow, params->device, params->def_period, params->min_period); return STATUS_SUCCESS; } @@ -2258,7 +2267,7 @@ static NTSTATUS pulse_is_started(void *args) struct pulse_stream *stream = handle_get_stream(params->stream); pulse_lock(); - params->started = pulse_stream_valid(stream) && stream->started; + params->result = pulse_stream_valid(stream) && stream->started ? S_OK : S_FALSE; pulse_unlock(); return STATUS_SUCCESS; @@ -2267,6 +2276,7 @@ static NTSTATUS pulse_is_started(void *args) static BOOL get_device_path(PhysDevice *dev, struct get_prop_value_params *params) { const GUID *guid = params->guid; + PROPVARIANT *out = params->value; UINT serial_number; char path[128]; int len; @@ -2288,9 +2298,19 @@ static BOOL get_device_path(PhysDevice *dev, struct get_prop_value_params *param break; } - ntdll_umbstowcs(path, len + 1, params->wstr, ARRAY_SIZE(params->wstr)); + if (*params->buffer_size < ++len * sizeof(WCHAR)) { + params->result = E_NOT_SUFFICIENT_BUFFER; + *params->buffer_size = len * sizeof(WCHAR); + return FALSE; + } + + out->vt = VT_LPWSTR; + out->pwszVal = params->buffer; + + ntdll_umbstowcs(path, len, out->pwszVal, len); + + params->result = S_OK; - params->vt = VT_LPWSTR; return TRUE; } @@ -2308,7 +2328,7 @@ static NTSTATUS pulse_get_prop_value(void *args) params->result = S_OK; LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) { - if (strcmp(params->pulse_name, dev->pulse_name)) + if (strcmp(params->device, dev->pulse_name)) continue; if (IsEqualPropertyKey(*params->prop, devicepath_key)) { if (!get_device_path(dev, params)) @@ -2317,20 +2337,20 @@ static NTSTATUS pulse_get_prop_value(void *args) } else if (IsEqualGUID(¶ms->prop->fmtid, &PKEY_AudioEndpoint_GUID)) { switch (params->prop->pid) { case 0: /* FormFactor */ - params->vt = VT_UI4; - params->ulVal = dev->form; + params->value->vt = VT_UI4; + params->value->ulVal = dev->form; return STATUS_SUCCESS; case 3: /* PhysicalSpeakers */ if (!dev->channel_mask) goto fail; - params->vt = VT_UI4; - params->ulVal = dev->channel_mask; + params->value->vt = VT_UI4; + params->value->ulVal = dev->channel_mask; return STATUS_SUCCESS; default: - break; + params->result = E_NOTIMPL; } } - params->result = E_NOTIMPL; + return STATUS_SUCCESS; } @@ -2355,6 +2375,7 @@ const unixlib_entry_t __wine_unix_call_funcs[] = pulse_release_render_buffer, pulse_get_capture_buffer, pulse_release_capture_buffer, + NULL, pulse_get_mix_format, pulse_get_device_period, pulse_get_buffer_size, @@ -2368,6 +2389,10 @@ const unixlib_entry_t __wine_unix_call_funcs[] = pulse_test_connect, pulse_is_started, pulse_get_prop_value, + NULL, + NULL, + NULL, + NULL, }; #ifdef _WIN64 @@ -2417,11 +2442,12 @@ static NTSTATUS pulse_wow64_create_stream(void *args) struct { PTR32 name; - PTR32 pulse_name; - EDataFlow dataflow; - AUDCLNT_SHAREMODE mode; + PTR32 device; + EDataFlow flow; + AUDCLNT_SHAREMODE share; DWORD flags; REFERENCE_TIME duration; + REFERENCE_TIME period; PTR32 fmt; HRESULT result; PTR32 channel_count; @@ -2430,11 +2456,12 @@ static NTSTATUS pulse_wow64_create_stream(void *args) struct create_stream_params params = { .name = ULongToPtr(params32->name), - .pulse_name = ULongToPtr(params32->pulse_name), - .dataflow = params32->dataflow, - .mode = params32->mode, + .device = ULongToPtr(params32->device), + .flow = params32->flow, + .share = params32->share, .flags = params32->flags, .duration = params32->duration, + .period = params32->period, .fmt = ULongToPtr(params32->fmt), .channel_count = ULongToPtr(params32->channel_count), .stream = ULongToPtr(params32->stream) @@ -2449,13 +2476,13 @@ static NTSTATUS pulse_wow64_release_stream(void *args) struct { stream_handle stream; - PTR32 timer; + PTR32 timer_thread; HRESULT result; } *params32 = args; struct release_stream_params params = { .stream = params32->stream, - .timer = ULongToHandle(params32->timer) + .timer_thread = ULongToHandle(params32->timer_thread) }; pulse_release_stream(¶ms); params32->result = params.result; @@ -2516,14 +2543,14 @@ static NTSTATUS pulse_wow64_get_mix_format(void *args) { struct { - PTR32 pulse_name; + PTR32 device; EDataFlow flow; PTR32 fmt; HRESULT result; } *params32 = args; struct get_mix_format_params params = { - .pulse_name = ULongToPtr(params32->pulse_name), + .device = ULongToPtr(params32->device), .flow = params32->flow, .fmt = ULongToPtr(params32->fmt), }; @@ -2536,7 +2563,7 @@ static NTSTATUS pulse_wow64_get_device_period(void *args) { struct { - PTR32 pulse_name; + PTR32 device; EDataFlow flow; HRESULT result; PTR32 def_period; @@ -2544,7 +2571,7 @@ static NTSTATUS pulse_wow64_get_device_period(void *args) } *params32 = args; struct get_device_period_params params = { - .pulse_name = ULongToPtr(params32->pulse_name), + .device = ULongToPtr(params32->device), .flow = params32->flow, .def_period = ULongToPtr(params32->def_period), .min_period = ULongToPtr(params32->min_period), @@ -2721,42 +2748,55 @@ static NTSTATUS pulse_wow64_test_connect(void *args) static NTSTATUS pulse_wow64_get_prop_value(void *args) { - struct + struct propvariant32 { - PTR32 pulse_name; - PTR32 guid; - PTR32 prop; - EDataFlow flow; - HRESULT result; - VARTYPE vt; + WORD vt; + WORD pad1, pad2, pad3; union { - WCHAR wstr[128]; ULONG ulVal; + PTR32 ptr; + ULARGE_INTEGER uhVal; }; + } *value32; + struct + { + PTR32 device; + EDataFlow flow; + PTR32 guid; + PTR32 prop; + HRESULT result; + PTR32 value; + PTR32 buffer; /* caller allocated buffer to hold value's strings */ + PTR32 buffer_size; } *params32 = args; + PROPVARIANT value; struct get_prop_value_params params = { - .pulse_name = ULongToPtr(params32->pulse_name), + .device = ULongToPtr(params32->device), + .flow = params32->flow, .guid = ULongToPtr(params32->guid), .prop = ULongToPtr(params32->prop), - .flow = params32->flow, + .value = &value, + .buffer = ULongToPtr(params32->buffer), + .buffer_size = ULongToPtr(params32->buffer_size) }; pulse_get_prop_value(¶ms); params32->result = params.result; - params32->vt = params.vt; if (SUCCEEDED(params.result)) { - switch (params.vt) + value32 = UlongToPtr(params32->value); + value32->vt = value.vt; + switch (value.vt) { case VT_UI4: - params32->ulVal = params.ulVal; + value32->ulVal = value.ulVal; break; case VT_LPWSTR: - wcscpy(params32->wstr, params.wstr); + value32->ptr = params32->buffer; break; default: - FIXME("Unhandled vt %04x\n", params.vt); + FIXME("Unhandled vt %04x\n", value.vt); } } return STATUS_SUCCESS; @@ -2778,6 +2818,7 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = pulse_release_render_buffer, pulse_wow64_get_capture_buffer, pulse_release_capture_buffer, + NULL, pulse_wow64_get_mix_format, pulse_wow64_get_device_period, pulse_wow64_get_buffer_size, @@ -2791,6 +2832,10 @@ const unixlib_entry_t __wine_unix_call_wow64_funcs[] = pulse_wow64_test_connect, pulse_is_started, pulse_wow64_get_prop_value, + NULL, + NULL, + NULL, + NULL, }; #endif /* _WIN64 */ diff --git a/dlls/winepulse.drv/unixlib.h b/dlls/winepulse.drv/unixlib.h deleted file mode 100644 index 1481a5db4b8..00000000000 --- a/dlls/winepulse.drv/unixlib.h +++ /dev/null @@ -1,263 +0,0 @@ -/* - * Copyright 2021 Jacek Caban for CodeWeavers - * - * This library is free software; you can redistribute it and/or - * modify it under the terms of the GNU Lesser General Public - * License as published by the Free Software Foundation; either - * version 2.1 of the License, or (at your option) any later version. - * - * This library is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU - * Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public - * License along with this library; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA - */ - -#include "wine/list.h" -#include "wine/unixlib.h" - -#define MAX_PULSE_NAME_LEN 256 - -typedef UINT64 stream_handle; - -enum phys_device_bus_type { - phys_device_bus_invalid = -1, - phys_device_bus_pci, - phys_device_bus_usb -}; - -struct endpoint -{ - unsigned int name; - unsigned int pulse_name; -}; - -struct main_loop_params -{ - HANDLE event; -}; - -struct get_endpoint_ids_params -{ - EDataFlow flow; - struct endpoint *endpoints; - unsigned int size; - HRESULT result; - unsigned int num; - unsigned int default_idx; -}; - -struct create_stream_params -{ - const char *name; - const char *pulse_name; - EDataFlow dataflow; - AUDCLNT_SHAREMODE mode; - DWORD flags; - REFERENCE_TIME duration; - const WAVEFORMATEX *fmt; - HRESULT result; - UINT32 *channel_count; - stream_handle *stream; -}; - -struct release_stream_params -{ - stream_handle stream; - HANDLE timer; - HRESULT result; -}; - -struct start_params -{ - stream_handle stream; - HRESULT result; -}; - -struct stop_params -{ - stream_handle stream; - HRESULT result; -}; - -struct reset_params -{ - stream_handle stream; - HRESULT result; -}; - -struct timer_loop_params -{ - stream_handle stream; -}; - -struct get_render_buffer_params -{ - stream_handle stream; - UINT32 frames; - HRESULT result; - BYTE **data; -}; - -struct release_render_buffer_params -{ - stream_handle stream; - UINT32 written_frames; - DWORD flags; - HRESULT result; -}; - -struct get_capture_buffer_params -{ - stream_handle stream; - HRESULT result; - BYTE **data; - UINT32 *frames; - DWORD *flags; - UINT64 *devpos; - UINT64 *qpcpos; -}; - -struct release_capture_buffer_params -{ - stream_handle stream; - BOOL done; - HRESULT result; -}; - -struct get_mix_format_params -{ - const char *pulse_name; - EDataFlow flow; - WAVEFORMATEXTENSIBLE *fmt; - HRESULT result; -}; - -struct get_device_period_params -{ - const char *pulse_name; - EDataFlow flow; - HRESULT result; - REFERENCE_TIME *def_period; - REFERENCE_TIME *min_period; -}; - -struct get_buffer_size_params -{ - stream_handle stream; - HRESULT result; - UINT32 *size; -}; - -struct get_latency_params -{ - stream_handle stream; - HRESULT result; - REFERENCE_TIME *latency; -}; - -struct get_current_padding_params -{ - stream_handle stream; - HRESULT result; - UINT32 *padding; -}; - -struct get_next_packet_size_params -{ - stream_handle stream; - HRESULT result; - UINT32 *frames; -}; - -struct get_frequency_params -{ - stream_handle stream; - HRESULT result; - UINT64 *freq; -}; - -struct get_position_params -{ - stream_handle stream; - BOOL device; - HRESULT result; - UINT64 *pos; - UINT64 *qpctime; -}; - -struct set_volumes_params -{ - stream_handle stream; - float master_volume; - const float *volumes; - const float *session_volumes; -}; - -struct set_event_handle_params -{ - stream_handle stream; - HANDLE event; - HRESULT result; -}; - -struct test_connect_params -{ - const char *name; - HRESULT result; -}; - -struct is_started_params -{ - stream_handle stream; - BOOL started; -}; - -struct get_prop_value_params -{ - const char *pulse_name; - const GUID *guid; - const PROPERTYKEY *prop; - EDataFlow flow; - HRESULT result; - VARTYPE vt; - union - { - WCHAR wstr[128]; - ULONG ulVal; - }; -}; - -enum unix_funcs -{ - process_attach, - process_detach, - main_loop, - get_endpoint_ids, - create_stream, - release_stream, - start, - stop, - reset, - timer_loop, - get_render_buffer, - release_render_buffer, - get_capture_buffer, - release_capture_buffer, - get_mix_format, - get_device_period, - get_buffer_size, - get_latency, - get_current_padding, - get_next_packet_size, - get_frequency, - get_position, - set_volumes, - set_event_handle, - test_connect, - is_started, - get_prop_value, -}; diff --git a/include/bcrypt.h b/include/bcrypt.h index ba44c01bbc9..c9c4cb7b1fd 100644 --- a/include/bcrypt.h +++ b/include/bcrypt.h @@ -159,6 +159,7 @@ static const WCHAR BCRYPT_AES_ALGORITHM[] = {'A','E','S',0}; static const WCHAR BCRYPT_DES_ALGORITHM[] = {'D','E','S',0}; static const WCHAR BCRYPT_DSA_ALGORITHM[] = {'D','S','A',0}; static const WCHAR BCRYPT_ECDH_P256_ALGORITHM[] = {'E','C','D','H','_','P','2','5','6',0}; +static const WCHAR BCRYPT_ECDH_P384_ALGORITHM[] = {'E','C','D','H','_','P','3','8','4',0}; static const WCHAR BCRYPT_ECDSA_P256_ALGORITHM[] = {'E','C','D','S','A','_','P','2','5','6',0}; static const WCHAR BCRYPT_ECDSA_P384_ALGORITHM[] = {'E','C','D','S','A','_','P','3','8','4',0}; static const WCHAR BCRYPT_ECDSA_P521_ALGORITHM[] = {'E','C','D','S','A','_','P','5','2','1',0}; diff --git a/server/sock.c b/server/sock.c index 7d7e470be28..4e57d6774a6 100644 --- a/server/sock.c +++ b/server/sock.c @@ -3468,15 +3468,19 @@ DECL_HANDLER(recv_socket) * asyncs will not consume all available data; if there's no data * available, the current request won't be immediately satiable. */ - struct pollfd pollfd; - pollfd.fd = get_unix_fd( sock->fd ); - pollfd.events = req->oob ? POLLPRI : POLLIN; - pollfd.revents = 0; - if (poll(&pollfd, 1, 0) >= 0 && pollfd.revents) + if ((!req->force_async && sock->nonblocking) || + check_fd_events( sock->fd, req->oob && !is_oobinline( sock ) ? POLLPRI : POLLIN )) { /* Give the client opportunity to complete synchronously. * If it turns out that the I/O request is not actually immediately satiable, - * the client may then choose to re-queue the async (with STATUS_PENDING). */ + * the client may then choose to re-queue the async (with STATUS_PENDING). + * + * Note: If the nonblocking flag is set, we don't poll the socket + * here and always opt for synchronous completion first. This is + * because the application has probably seen POLLIN already from a + * preceding select()/poll() call before it requested to receive + * data. + */ status = STATUS_ALERTED; } } @@ -3568,15 +3572,27 @@ DECL_HANDLER(send_socket) * asyncs will not consume all available space; if there's no space * available, the current request won't be immediately satiable. */ - struct pollfd pollfd; - pollfd.fd = get_unix_fd( sock->fd ); - pollfd.events = POLLOUT; - pollfd.revents = 0; - if (poll(&pollfd, 1, 0) >= 0 && pollfd.revents) + if ((!req->force_async && sock->nonblocking) || check_fd_events( sock->fd, POLLOUT )) { /* Give the client opportunity to complete synchronously. * If it turns out that the I/O request is not actually immediately satiable, - * the client may then choose to re-queue the async (with STATUS_PENDING). */ + * the client may then choose to re-queue the async (with STATUS_PENDING). + * + * Note: If the nonblocking flag is set, we don't poll the socket + * here and always opt for synchronous completion first. This is + * because the application has probably seen POLLOUT already from a + * preceding select()/poll() call before it requested to send data. + * + * Furthermore, some applications expect that any send() call on a + * socket that has indicated POLLOUT beforehand never fails with + * WSAEWOULDBLOCK. It's possible that Linux poll() may yield + * POLLOUT on the first call but not the second, even if no send() + * call has been made in the meanwhile. This can happen for a + * number of reasons; for example, TCP fragmentation may consume + * extra buffer space for each packet that has been split out, or + * the TCP/IP networking stack may decide to shrink the send buffer + * due to memory pressure. + */ status = STATUS_ALERTED; } } -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/706
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=121962 Your paranoid android. === build (build log) === error: patch failed: dlls/ddraw/ddraw.c:49 error: patch failed: dlls/ddraw/tests/d3d.c:488 error: patch failed: dlls/ddraw/tests/ddraw1.c:15145 error: patch failed: dlls/ddraw/tests/ddraw2.c:16091 error: patch failed: dlls/ddraw/tests/ddraw4.c:19160 error: patch failed: dlls/ddraw/tests/ddraw7.c:19390 error: patch failed: dlls/msvcrt/concurrency.c:24 error: patch failed: dlls/qasf/tests/asfreader.c:513 error: patch failed: dlls/winepulse.drv/mmdevdrv.c:2 error: patch failed: dlls/winepulse.drv/pulse.c:2 error: patch failed: include/bcrypt.h:159 error: patch failed: server/sock.c:3468 Task: Patch failed to apply === debian11 (build log) === error: patch failed: dlls/ddraw/ddraw.c:49 error: patch failed: dlls/ddraw/tests/d3d.c:488 error: patch failed: dlls/ddraw/tests/ddraw1.c:15145 error: patch failed: dlls/ddraw/tests/ddraw2.c:16091 error: patch failed: dlls/ddraw/tests/ddraw4.c:19160 error: patch failed: dlls/ddraw/tests/ddraw7.c:19390 error: patch failed: dlls/msvcrt/concurrency.c:24 error: patch failed: dlls/qasf/tests/asfreader.c:513 error: patch failed: dlls/winepulse.drv/mmdevdrv.c:2 error: patch failed: dlls/winepulse.drv/pulse.c:2 error: patch failed: include/bcrypt.h:159 error: patch failed: server/sock.c:3468 Task: Patch failed to apply === debian11 (build log) === error: patch failed: dlls/ddraw/ddraw.c:49 error: patch failed: dlls/ddraw/tests/d3d.c:488 error: patch failed: dlls/ddraw/tests/ddraw1.c:15145 error: patch failed: dlls/ddraw/tests/ddraw2.c:16091 error: patch failed: dlls/ddraw/tests/ddraw4.c:19160 error: patch failed: dlls/ddraw/tests/ddraw7.c:19390 error: patch failed: dlls/msvcrt/concurrency.c:24 error: patch failed: dlls/qasf/tests/asfreader.c:513 error: patch failed: dlls/winepulse.drv/mmdevdrv.c:2 error: patch failed: dlls/winepulse.drv/pulse.c:2 error: patch failed: include/bcrypt.h:159 error: patch failed: server/sock.c:3468 Task: Patch failed to apply
From: Etaash Mathamsetty <etaash.mathamsetty(a)gmail.com> try squashing commits again fix print formatting fix potential logic error fix errors improve formatting bcrypt: Fix the non-PE build after ECDH_P384 was added. This fixes non-PE builds after 5253c8d77e8e7dc5770981e97e67348f393b99b9. Signed-off-by: Martin Storsjö <martin(a)martin.st> ddraw/tests: Add a comment to note that tests in d3d.c are deprecated. And new tests should be added to tests/ddraw{1,2,4,7}.c. ddraw/tests: Move the capability tests for enumerated devices. Move the capability tests for enumerated devices from d3d.c to ddraw{1,2,4}.c. ddraw/tests: Add more capability tests for enumerated devices. Add tests for D3DDEVCAPS_HWTRANSFORMANDLIGHT and D3DDEVCAPS_DRAWPRIMITIVES2EX. Signed-off-by: Zhiyi Zhang <zzhang(a)codeweavers.com> ddraw: Don't report unsupported device capabilities in d3d7_EnumDevices(). Fix Battle Realms: Zen Edition failing to start. The game expects to find a device without D3DDEVCAPS_HWTRANSFORMANDLIGHT. ddraw: Don't report unsupported device capabilities in d3d3_EnumDevices(). winepulse: Adapt "endpoint" struct to mmdevapi's. winepulse: Adapt "create_stream_params" struct to mmdevapi's. winepulse: Adapt "release_stream_params" struct to mmdevapi's. winepulse: Adapt "release_render_buffer_params" struct to mmdevapi's. winepulse: Adapt "get_capture_buffer_params" struct to mmdevapi's. winepulse: Adapt "get_mix_format_params" struct to mmdevapi's. winepulse: Adapt "get_device_period_params" struct to mmdevapi's. winepulse: Adapt "is_started_params" struct to mmdevapi's. winepulse: Adapt "get_prop_value_params" struct to mmdevapi's. winepulse: Switch to mmdevapi's unixlib.h. server: Use POLLIN instead of POLLPRI if the socket is in oobinline mode. server: Use check_fd_events() instead of calling poll() directly. server: Always prefer synchronous I/O in nonblocking mode. foobar2000.exe's UPnP Media Renderer component (foo_out_upnp.dll) expects that, if a select() call completes successfully with a non-empty writefds set, any immediately following send() call on a socket in the writefds set never fails with WSAEWOULDBLOCK. On Wine, the Winsock select() and send() implementations both call the Unix poll(2) under the hood to test if I/O is possible on the socket. As it turns out, it's entirely possible that Linux poll() may yield POLLOUT on the first call (by select) but *not* the second (by send), even if no send() call has been made in the meanwhile. On Linux (as of v5.19), a connected (ESTABLISHED) TCP socket that has not been shut down indicates (E)POLLOUT only if the ratio of sk_wmem_queued (the amount of bytes queued in the send buffer) to sk_sndbuf (the size of send buffer size itself, which can be retrieved via SO_SNDBUF) is below a certain threshold. Therefore, a falling edge in POLLOUT can be triggered due to a number of reasons: 1. TCP fragmentation. Once a TCP packet is split out from a larger sk_buff, it incurs extra bookkeeping overhead (e.g. sk_buff header) that is counted in sk_wmem_queued alongside application data. See also: tcp_fragment(), tso_fragment() (Linux 5.19). 2. Control packets (e.g. MTU probing). Such packets share the same buffer with application-initiated packets, and thus counted in sk_wmem_queued. See also: sk_wmem_queued_add() callers (Linux 5.19). 3. Memory pressure. This causes sk_sndbuf to shrink. See also: sk_stream_moderate_sndbuf() callers (Linux 5.19). Fix this by always attempting synchronous I/O first if req->force_async is unset and the nonblocking flag is set. Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=53486 msvcr100: Factor out the mapping of a context to a scheduler. Signed-off-by: Torge Matthies <tmatthies(a)codeweavers.com> msvcr100: Implement _StructuredTaskCollection::_Schedule and _Schedule_loc. Signed-off-by: Torge Matthies <tmatthies(a)codeweavers.com> msvcr100: Set scheduler in tasks created with ScheduleTask function. qasf/tests: Test ASF Reader filter initial state and pins. qasf/tests: Test ASF Reader filter threading wrt. ReceiveCanBlock. fix potential logic error improve formatting --- dlls/ntoskrnl.exe/instr.c | 43 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/dlls/ntoskrnl.exe/instr.c b/dlls/ntoskrnl.exe/instr.c index 8f1aa4d45a3..85d48cef7aa 100644 --- a/dlls/ntoskrnl.exe/instr.c +++ b/dlls/ntoskrnl.exe/instr.c @@ -890,7 +890,50 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) } break; /* Unable to emulate it */ } + case 0x38: + case 0x39: /* cmp r/m r/m */ + { + ULONG64 *data = (ULONG64*)INSTR_GetOperandAddr(context, instr + 1, prefixlen + 1, long_addr, rex, segprefix, &len); + ULONG64 *data2 = (ULONG64*)INSTR_GetOperandAddr(context, instr + 2, prefixlen + 2, long_addr, rex, segprefix, &len); + SIZE_T offset = (BYTE*)data - user_shared_data; + SIZE_T offset2 = (BYTE*)data2 - user_shared_data; + SIZE_T data_size = get_op_size(long_op, rex); + BOOL is_user_shared_data = FALSE; + ULONG64 cmp1, cmp2, bitmask; + if(offset <= KSHARED_USER_DATA_PAGE_SIZE - data_size) + { + TRACE("USD offset %#x at %p\n",(unsigned int) offset, (void*) context->Rip); + data = (ULONG64*)(wine_user_shared_data + offset); + is_user_shared_data = TRUE; + } + if(offset2 <= KSHARED_USER_DATA_PAGE_SIZE - data_size) + { + TRACE("USD offset %#x at %p\n", (unsigned int) offset2, (void*) context->Rip); + data2 = (ULONG64*)(wine_user_shared_data + offset2); + is_user_shared_data = TRUE; + } + if(is_user_shared_data) + { + /* clear ZF and CF */ + context->EFlags &= ~(1UL << 6); + context->EFlags &= ~(1UL); + + bitmask = ((1ULL << (8 * data_size)) - 1); + /* FIXME("bitmask %llx\n", bitmask); */ + cmp1 = (*data) & bitmask; + cmp2 = (*data2) & bitmask; + + if(cmp1 == cmp2) + context->EFlags |= (1UL << 6); /* ZF */ + else if(cmp1 < cmp2) + context->EFlags |= 1UL; /* CF */ + + context->Rip += prefixlen + len + 1; + return ExceptionContinueExecution; + } + break; + } case 0xa0: /* mov Ob, AL */ case 0xa1: /* mov Ovqp, rAX */ { -- GitLab https://gitlab.winehq.org/wine/wine/-/merge_requests/706
Hi, It looks like your patch introduced the new failures shown below. Please investigate and fix them before resubmitting your patch. If they are not new, fixing them anyway would help a lot. Otherwise please ask for the known failures list to be updated. The full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=121963 Your paranoid android. === debian11 (build log) === error: patch failed: dlls/ddraw/ddraw.c:49 error: patch failed: dlls/ddraw/tests/d3d.c:488 error: patch failed: dlls/ddraw/tests/ddraw1.c:15145 error: patch failed: dlls/ddraw/tests/ddraw2.c:16091 error: patch failed: dlls/ddraw/tests/ddraw4.c:19160 error: patch failed: dlls/ddraw/tests/ddraw7.c:19390 error: patch failed: dlls/msvcrt/concurrency.c:24 error: patch failed: dlls/qasf/tests/asfreader.c:513 error: patch failed: dlls/winepulse.drv/mmdevdrv.c:2 error: patch failed: dlls/winepulse.drv/pulse.c:2 error: patch failed: include/bcrypt.h:159 error: patch failed: server/sock.c:3468 error: patch failed: dlls/ntoskrnl.exe/instr.c:890 Task: Patch failed to apply === debian11 (build log) === error: patch failed: dlls/ddraw/ddraw.c:49 error: patch failed: dlls/ddraw/tests/d3d.c:488 error: patch failed: dlls/ddraw/tests/ddraw1.c:15145 error: patch failed: dlls/ddraw/tests/ddraw2.c:16091 error: patch failed: dlls/ddraw/tests/ddraw4.c:19160 error: patch failed: dlls/ddraw/tests/ddraw7.c:19390 error: patch failed: dlls/msvcrt/concurrency.c:24 error: patch failed: dlls/qasf/tests/asfreader.c:513 error: patch failed: dlls/winepulse.drv/mmdevdrv.c:2 error: patch failed: dlls/winepulse.drv/pulse.c:2 error: patch failed: include/bcrypt.h:159 error: patch failed: server/sock.c:3468 error: patch failed: dlls/ntoskrnl.exe/instr.c:890 Task: Patch failed to apply
participants (3)
-
Etaash Mathamsetty -
Etaash Mathamsetty (@etaash.mathamsetty) -
Marvin