From: Etaash Mathamsetty etaash.mathamsetty@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@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@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@codeweavers.com
msvcr100: Implement _StructuredTaskCollection::_Schedule and _Schedule_loc.
Signed-off-by: Torge Matthies tmatthies@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 | 45 ++-- 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, 1577 insertions(+), 552 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@Context@Concurrency@@SAPAV12@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@_StructuredTaskCollection@details@Concurrency@@QAAXPAV_UnrealizedChore@23@PAVlocation@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@_StructuredTaskCollection@details@Concurrency@@QAA?AW4_TaskCollectionStatus@23@PAV_UnrealizedChore@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 c9c61513a33..85d48cef7aa 100644 --- a/dlls/ntoskrnl.exe/instr.c +++ b/dlls/ntoskrnl.exe/instr.c @@ -891,33 +891,44 @@ static DWORD emulate_instruction( EXCEPTION_RECORD *rec, CONTEXT *context ) break; /* Unable to emulate it */ } case 0x38: - case 0x39: /* cmp r/m r/m*/ + case 0x39: /* cmp r/m r/m */ { - BYTE *data = INSTR_GetOperandAddr(context, instr + 1, prefixlen + 1, long_addr, rex, segprefix, &len); - BYTE *data2 = INSTR_GetOperandAddr(context, instr + 2, prefixlen + 2, long_addr, rex, segprefix, &len); - SIZE_T offset = data - user_shared_data; - SIZE_T offset2 = data2 - user_shared_data; + 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) { - if(offset2 <= KSHARED_USER_DATA_PAGE_SIZE - data_size) - { - data2 = wine_user_shared_data + offset2; - TRACE("USD offset2 %#x at %#p", (unsigned int)offset, (void*)context->Rip); - } - TRACE("USD offset %#x at %#p\n",(unsigned int) offset, (void*)context->Rip); - + 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);
- if(*(wine_user_shared_data + offset) == *data2) - { + 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(*(wine_user_shared_data + offset) < *data2){ + else if(cmp1 < cmp2) context->EFlags |= 1UL; /* CF */ - } + context->Rip += prefixlen + len + 1; return ExceptionContinueExecution; } 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; } }