Rebase against 4853f65c844de8277b8b0420df1a2cdb1c5b17c8.

mfplat-streaming-support disabled once again.
This commit is contained in:
Alistair Leslie-Hughes 2022-02-23 14:27:11 +11:00
parent bcfed21ea1
commit 05ea40b936
11 changed files with 182 additions and 1512 deletions

View File

@ -1 +1,2 @@
Fixes: [49692] Multiple applications need a Media Foundation media source implementation
Disabled: True

View File

@ -51,7 +51,7 @@ usage()
# Get the upstream commit sha
upstream_commit()
{
echo "53cb28e6d9daa7cbcc190cd02aeaba37c297adc4"
echo "4853f65c844de8277b8b0420df1a2cdb1c5b17c8"
}
# Show version information
@ -127,7 +127,6 @@ patch_enable_all ()
enable_krnl386_exe16_Invalid_Console_Handles="$1"
enable_libs_Unicode_Collation="$1"
enable_loader_KeyboardLayouts="$1"
enable_mfplat_streaming_support="$1"
enable_mmsystem_dll16_MIDIHDR_Refcount="$1"
enable_mountmgr_DosDevices="$1"
enable_mscoree_CorValidateImage="$1"
@ -411,9 +410,6 @@ patch_enable ()
loader-KeyboardLayouts)
enable_loader_KeyboardLayouts="$2"
;;
mfplat-streaming-support)
enable_mfplat_streaming_support="$2"
;;
mmsystem.dll16-MIDIHDR_Refcount)
enable_mmsystem_dll16_MIDIHDR_Refcount="$2"
;;
@ -2233,112 +2229,6 @@ if test "$enable_loader_KeyboardLayouts" -eq 1; then
patch_apply loader-KeyboardLayouts/0002-user32-Improve-GetKeyboardLayoutList.patch
fi
# Patchset mfplat-streaming-support
# |
# | This patchset fixes the following Wine bugs:
# | * [#49692] Multiple applications need a Media Foundation media source implementation
# |
# | Modified files:
# | * dlls/mf/tests/mf.c, dlls/mf/topology.c, dlls/mfplat/main.c, dlls/qasf/Makefile.in, dlls/qasf/asfreader.c,
# | dlls/quartz/filtergraph.c, dlls/winegstreamer/Makefile.in, dlls/winegstreamer/aac_decoder.c,
# | dlls/winegstreamer/audioconvert.c, dlls/winegstreamer/colorconvert.c, dlls/winegstreamer/decode_transform.c,
# | dlls/winegstreamer/gst_private.h, dlls/winegstreamer/h264_decoder.c, dlls/winegstreamer/main.c,
# | dlls/winegstreamer/media_source.c, dlls/winegstreamer/mfplat.c, dlls/winegstreamer/quartz_parser.c,
# | dlls/winegstreamer/unix_private.h, dlls/winegstreamer/unixlib.h, dlls/winegstreamer/wg_format.c,
# | dlls/winegstreamer/wg_parser.c, dlls/winegstreamer/wg_transform.c, dlls/winegstreamer/winegstreamer_classes.idl,
# | dlls/winegstreamer/wm_reader.c, dlls/winegstreamer/wma_decoder.c, include/wmcodecdsp.idl
# |
if test "$enable_mfplat_streaming_support" -eq 1; then
patch_apply mfplat-streaming-support/0001-winegstreamer-HACK-Use-a-different-gst-registry-file.patch
patch_apply mfplat-streaming-support/0002-winegstreamer-HACK-Try-harder-to-register-winegstrea.patch
patch_apply mfplat-streaming-support/0003-mfplat-Register-winegstreamer-interfaces-on-load.patch
patch_apply mfplat-streaming-support/0004-Revert-winegstreamer-Create-static-pads-on-wg_transf.patch
patch_apply mfplat-streaming-support/0005-Revert-winegstreamer-Introduce-new-wg_transform-stru.patch
patch_apply mfplat-streaming-support/0006-Revert-winegstreamer-Introduce-new-WG_MAJOR_TYPE_WMA.patch
patch_apply mfplat-streaming-support/0007-Revert-winegstreamer-Move-format-helpers-to-a-dedica.patch
patch_apply mfplat-streaming-support/0008-winegstreamer-Allow-videoconvert-to-parallelize.patch
patch_apply mfplat-streaming-support/0009-HACK-winegstreamer-Use-capssetter-to-ignore-non-defa.patch
patch_apply mfplat-streaming-support/0010-HACK-quartz-Keep-a-reference-on-the-IMediaPosition-i.patch
patch_apply mfplat-streaming-support/0011-mfplat-Stub-out-MFCreateDXGIDeviceManager-to-avoid-t.patch
patch_apply mfplat-streaming-support/0012-HACK-qasf-Implement-ASF-Reader-filter-as-a-simple-fi.patch
patch_apply mfplat-streaming-support/0013-winegstreamer-Activate-source-pad-in-push-mode-if-it.patch
patch_apply mfplat-streaming-support/0014-winegstreamer-Push-stream-start-and-segment-events-i.patch
patch_apply mfplat-streaming-support/0015-winegstreamer-Introduce-H.264-decoder-transform.patch
patch_apply mfplat-streaming-support/0016-winegstreamer-Implement-GetInputAvailableType-for-de.patch
patch_apply mfplat-streaming-support/0017-winegstreamer-Implement-GetOutputAvailableType-for-d.patch
patch_apply mfplat-streaming-support/0018-winegstreamer-Implement-SetInputType-for-decode-tran.patch
patch_apply mfplat-streaming-support/0019-winegstreamer-Implement-SetOutputType-for-decode-tra.patch
patch_apply mfplat-streaming-support/0020-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
patch_apply mfplat-streaming-support/0021-winegstreamer-Semi-stub-GetAttributes-for-decoder-tr.patch
patch_apply mfplat-streaming-support/0022-winegstreamer-Register-the-H.264-decoder-transform.patch
patch_apply mfplat-streaming-support/0023-winegstreamer-Introduce-AAC-decoder-transform.patch
patch_apply mfplat-streaming-support/0024-winegstreamer-Rename-GStreamer-objects-to-be-more-ge.patch
patch_apply mfplat-streaming-support/0025-winegstreamer-Report-streams-backwards-in-media-sour.patch
patch_apply mfplat-streaming-support/0026-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
patch_apply mfplat-streaming-support/0027-winegstreamer-Semi-stub-Get-Attributes-functions-for.patch
patch_apply mfplat-streaming-support/0028-winegstreamer-Introduce-color-conversion-transform.patch
patch_apply mfplat-streaming-support/0029-winegstreamer-Register-the-color-conversion-transfor.patch
patch_apply mfplat-streaming-support/0030-winegstreamer-Implement-GetInputAvailableType-for-co.patch
patch_apply mfplat-streaming-support/0031-winegstreamer-Implement-SetInputType-for-color-conve.patch
patch_apply mfplat-streaming-support/0032-winegstreamer-Implement-GetOutputAvailableType-for-c.patch
patch_apply mfplat-streaming-support/0033-winegstreamer-Implement-SetOutputType-for-color-conv.patch
patch_apply mfplat-streaming-support/0034-winegstreamer-Implement-ProcessMessage-for-color-con.patch
patch_apply mfplat-streaming-support/0035-winegstreamer-Implement-Get-Input-Output-StreamInfo-.patch
patch_apply mfplat-streaming-support/0036-mf-topology-Forward-failure-from-SetOutputType-when-.patch
patch_apply mfplat-streaming-support/0037-winegstreamer-Handle-flush-command-in-audio-converst.patch
patch_apply mfplat-streaming-support/0038-winegstreamer-In-the-default-configuration-select-on.patch
patch_apply mfplat-streaming-support/0039-winegstreamer-Implement-IMFTransform-GetOutputCurren.patch
patch_apply mfplat-streaming-support/0040-winegstreamer-Implement-stream-draining-support.patch
patch_apply mfplat-streaming-support/0041-winegstreamer-Add-an-explicit-result-to-wg_parser_pu.patch
patch_apply mfplat-streaming-support/0042-winegstreamer-Unblock-wg_parser_get_next_read_offset.patch
patch_apply mfplat-streaming-support/0043-winegstreamer-Update-offset-according-to-the-size-of.patch
patch_apply mfplat-streaming-support/0044-winegstreamer-Let-src_getrange_cb-allocate-the-buffe.patch
patch_apply mfplat-streaming-support/0045-winegstreamer-Implement-unseekable-stream-support.patch
patch_apply mfplat-streaming-support/0046-winegstreamer-Implement-Process-Input-Output-for-dec.patch
patch_apply mfplat-streaming-support/0047-winegstreamer-Implement-ProcessMessage-for-decoder-t.patch
patch_apply mfplat-streaming-support/0048-winegstreamer-Implement-Process-Input-Output-for-aud.patch
patch_apply mfplat-streaming-support/0049-winegstreamer-Implement-Process-Input-Output-for-col.patch
patch_apply mfplat-streaming-support/0050-winegstreamer-Implement-MF_SD_LANGUAGE.patch
patch_apply mfplat-streaming-support/0051-winegstreamer-Implement-MFT_MESSAGE_COMMAND_FLUSH-fo.patch
patch_apply mfplat-streaming-support/0052-winegstreamer-Add-videobox-element-and-aperture-supp.patch
patch_apply mfplat-streaming-support/0053-winegstreamer-Only-require-videobox-element-for-pars.patch
patch_apply mfplat-streaming-support/0054-winegstreamer-Feed-full-buffer-in-audio-converter-Pr.patch
patch_apply mfplat-streaming-support/0055-winegstreamer-Add-MFVideoFormat_ARGB32-output-for-th.patch
patch_apply mfplat-streaming-support/0056-winegstreamer-Return-S_OK-from-WMA-decoder-ProcessMe.patch
patch_apply mfplat-streaming-support/0057-winegstreamer-Introduce-new-wg_transform-struct.patch
patch_apply mfplat-streaming-support/0058-winegstreamer-Introduce-new-wg_encoded_format-struct.patch
patch_apply mfplat-streaming-support/0059-winegstreamer-Create-static-pads-on-wg_transform-str.patch
patch_apply mfplat-streaming-support/0060-winegstreamer-Lookup-create-and-link-a-decoder-eleme.patch
patch_apply mfplat-streaming-support/0061-winegstreamer-Send-stream-start-and-caps-events-on-c.patch
patch_apply mfplat-streaming-support/0062-winegstreamer-Add-an-audioconverter-and-audioresampl.patch
patch_apply mfplat-streaming-support/0063-winegstreamer-Implement-WMA-decoder-ProcessInput.patch
patch_apply mfplat-streaming-support/0064-winegstreamer-Implement-WMA-decoder-ProcessOutput.patch
patch_apply mfplat-streaming-support/0065-winegstreamer-Support-XMAudio2-input-format-in-WMA-d.patch
patch_apply mfplat-streaming-support/0066-winegstreamer-Introduce-new-H264-decoder-transform-s.patch
patch_apply mfplat-streaming-support/0067-winegstreamer-Return-S_OK-from-H264-decoder-GetAttri.patch
patch_apply mfplat-streaming-support/0068-winegstreamer-Return-S_OK-from-H264-decoder-ProcessM.patch
patch_apply mfplat-streaming-support/0069-winegstreamer-Implement-H264-decoder-SetInputType.patch
patch_apply mfplat-streaming-support/0070-winegstreamer-Implement-H264-decoder-GetOutputAvaila.patch
patch_apply mfplat-streaming-support/0071-winegstreamer-Implement-H264-decoder-GetInputAvailab.patch
patch_apply mfplat-streaming-support/0072-winegstreamer-Implement-H264-decoder-SetOutputType.patch
patch_apply mfplat-streaming-support/0073-winegstreamer-Implement-H264-decoder-GetInputStreamI.patch
patch_apply mfplat-streaming-support/0074-winegstreamer-Implement-H264-decoder-GetOutputStream.patch
patch_apply mfplat-streaming-support/0075-winegstreamer-Add-H264-encoded-format-support-in-wg_.patch
patch_apply mfplat-streaming-support/0076-winegstreamer-Implement-H264-decoder-ProcessInput.patch
patch_apply mfplat-streaming-support/0077-winegstreamer-Implement-H264-decoder-ProcessOutput.patch
patch_apply mfplat-streaming-support/0078-winegstreamer-Add-timestamps-and-duration-to-H264-de.patch
patch_apply mfplat-streaming-support/0079-winegstreamer-Support-dynamic-wg_transform-video-for.patch
patch_apply mfplat-streaming-support/0080-winegstreamer-Fixup-H264-decoder-NV12-plane-alignmen.patch
patch_apply mfplat-streaming-support/0081-winegstreamer-Use-an-optional-h264parse-wg_transform.patch
patch_apply mfplat-streaming-support/0082-HACK-winegstreamer-Fake-H264-timestamps-if-framerate.patch
patch_apply mfplat-streaming-support/0083-winegstreamer-Reset-internal-format-on-BEGIN_STREAMI.patch
patch_apply mfplat-streaming-support/0084-winegstreamer-Reimplement-AAC-decoder-using-wg_trans.patch
patch_apply mfplat-streaming-support/0085-winegstreamer-After-failing-to-create-decodebin-pars.patch
patch_apply mfplat-streaming-support/0086-fixup-winegstreamer-After-failing-to-create-decodebi.patch
patch_apply mfplat-streaming-support/0087-winegstreamer-Use-unlimited-buffering-for-the-WM-rea.patch
patch_apply mfplat-streaming-support/0088-HACK-winegstreamer-Report-streams-in-reverse-order-f.patch
fi
# Patchset mmsystem.dll16-MIDIHDR_Refcount
# |
# | This patchset fixes the following Wine bugs:
@ -3841,14 +3731,10 @@ fi
# | * [#37042] Implement exclusive mode in PulseAudio backend
# |
# | Modified files:
# | * dlls/winepulse.drv/Makefile.in, dlls/winepulse.drv/mmdevdrv.c, dlls/winepulse.drv/pulse.c, dlls/winepulse.drv/unixlib.h
# | * dlls/winepulse.drv/pulse.c
# |
if test "$enable_winepulse_PulseAudio_Support" -eq 1; then
patch_apply winepulse-PulseAudio_Support/0001-winepulse.drv-Use-a-separate-mainloop-and-ctx-for-pu.patch
patch_apply winepulse-PulseAudio_Support/0003-winepulse-expose-audio-devices-directly-to-programs.patch
patch_apply winepulse-PulseAudio_Support/0005-winepulse-implement-GetPropValue.patch
patch_apply winepulse-PulseAudio_Support/0006-winepulse-fetch-actual-program-name-if-possible.patch
patch_apply winepulse-PulseAudio_Support/0007-winepulse-return-PKEY_AudioEndpoint_PhysicalSpeakers.patch
fi
# Patchset winex11-CandidateWindowPos

View File

@ -1,18 +1,18 @@
From edb8be68e6c30043c6723f0928036b3a4bdb67bc Mon Sep 17 00:00:00 2001
From 012ebe712d84fa4242e3d44562aab45a5360b72c Mon Sep 17 00:00:00 2001
From: Sebastian Lackner <sebastian@fds-team.de>
Date: Wed, 4 Nov 2015 02:57:56 +0100
Subject: [PATCH] winepulse.drv: Use a separate mainloop and ctx for
pulse_test_connect.
---
dlls/winepulse.drv/pulse.c | 57 ++++++++++++++++++--------------------
1 file changed, 27 insertions(+), 30 deletions(-)
dlls/winepulse.drv/pulse.c | 59 ++++++++++++++++++--------------------
1 file changed, 28 insertions(+), 31 deletions(-)
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
index 55579ecda80..b91afe4b22b 100644
index 6552e4ce250..e82e6f4d9a7 100644
--- a/dlls/winepulse.drv/pulse.c
+++ b/dlls/winepulse.drv/pulse.c
@@ -428,7 +428,7 @@ static void convert_channel_map(const pa_channel_map *pa_map, WAVEFORMATEXTENSIB
@@ -587,7 +587,7 @@ static void convert_channel_map(const pa_channel_map *pa_map, WAVEFORMATEXTENSIB
fmt->dwChannelMask = pa_mask;
}
@ -21,7 +21,7 @@ index 55579ecda80..b91afe4b22b 100644
WAVEFORMATEX *wfx = &fmt->Format;
pa_stream *stream;
pa_channel_map map;
@@ -447,7 +447,7 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt) {
@@ -606,7 +606,7 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt) {
attr.minreq = attr.fragsize = pa_frame_size(&ss);
attr.prebuf = 0;
@ -30,7 +30,7 @@ index 55579ecda80..b91afe4b22b 100644
if (stream)
pa_stream_set_state_callback(stream, pulse_stream_state, NULL);
if (!stream)
@@ -458,7 +458,7 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt) {
@@ -617,7 +617,7 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt) {
else
ret = pa_stream_connect_record(stream, NULL, &attr, PA_STREAM_START_CORKED|PA_STREAM_FIX_RATE|PA_STREAM_FIX_CHANNELS|PA_STREAM_EARLY_REQUESTS);
if (ret >= 0) {
@ -39,7 +39,7 @@ index 55579ecda80..b91afe4b22b 100644
pa_stream_get_state(stream) == PA_STREAM_CREATING)
{}
if (pa_stream_get_state(stream) == PA_STREAM_READY) {
@@ -469,7 +469,7 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt) {
@@ -628,7 +628,7 @@ static void pulse_probe_settings(int render, WAVEFORMATEXTENSIBLE *fmt) {
else
length = pa_stream_get_buffer_attr(stream)->fragsize;
pa_stream_disconnect(stream);
@ -48,7 +48,7 @@ index 55579ecda80..b91afe4b22b 100644
pa_stream_get_state(stream) == PA_STREAM_READY)
{}
}
@@ -516,31 +516,32 @@ static NTSTATUS pulse_test_connect(void *args)
@@ -675,31 +675,32 @@ static NTSTATUS pulse_test_connect(void *args)
struct pulse_config *config = params->config;
pa_operation *o;
int ret;
@ -92,7 +92,7 @@ index 55579ecda80..b91afe4b22b 100644
if (state == PA_CONTEXT_FAILED || state == PA_CONTEXT_TERMINATED)
goto fail;
@@ -549,29 +550,27 @@ static NTSTATUS pulse_test_connect(void *args)
@@ -708,15 +709,15 @@ static NTSTATUS pulse_test_connect(void *args)
break;
}
@ -102,16 +102,20 @@ index 55579ecda80..b91afe4b22b 100644
TRACE("Test-connected to server %s with protocol version: %i.\n",
- pa_context_get_server(pulse_ctx),
- pa_context_get_server_protocol_version(pulse_ctx));
+ pa_context_get_server(ctx),
+ pa_context_get_server_protocol_version(ctx));
pa_context_get_server_protocol_version(pulse_ctx));
- pulse_probe_settings(1, &pulse_fmt[0]);
- pulse_probe_settings(0, &pulse_fmt[1]);
+ pulse_probe_settings(ml, ctx, 1, &pulse_fmt[0]);
+ pulse_probe_settings(ml, ctx, 0, &pulse_fmt[1]);
g_phys_speakers_mask = 0;
free_phys_device_lists();
list_init(&g_phys_speakers);
@@ -725,26 +726,24 @@ static NTSTATUS pulse_test_connect(void *args)
pulse_add_device(&g_phys_speakers, NULL, 0, Speakers, 0, "", "PulseAudio");
pulse_add_device(&g_phys_sources, NULL, 0, Microphone, 0, "", "PulseAudio");
- o = pa_context_get_sink_info_list(pulse_ctx, &pulse_phys_speakers_cb, NULL);
+ o = pa_context_get_sink_info_list(ctx, &pulse_phys_speakers_cb, NULL);
if (o) {
@ -122,6 +126,16 @@ index 55579ecda80..b91afe4b22b 100644
pa_operation_unref(o);
}
- o = pa_context_get_source_info_list(pulse_ctx, &pulse_phys_sources_cb, NULL);
+ o = pa_context_get_source_info_list(ctx, &pulse_phys_sources_cb, NULL);
if (o) {
- while (pa_mainloop_iterate(pulse_ml, 1, &ret) >= 0 &&
+ while (pa_mainloop_iterate(ml, 1, &ret) >= 0 &&
pa_operation_get_state(o) == PA_OPERATION_RUNNING)
{}
pa_operation_unref(o);
}
- pa_context_unref(pulse_ctx);
- pulse_ctx = NULL;
- pa_mainloop_free(pulse_ml);
@ -129,9 +143,9 @@ index 55579ecda80..b91afe4b22b 100644
+ pa_context_unref(ctx);
+ pa_mainloop_free(ml);
config->speakers_mask = g_phys_speakers_mask;
config->modes[0].format = pulse_fmt[0];
@@ -587,10 +586,8 @@ static NTSTATUS pulse_test_connect(void *args)
config->modes[0].def_period = pulse_def_period[0];
@@ -759,10 +758,8 @@ static NTSTATUS pulse_test_connect(void *args)
return STATUS_SUCCESS;
fail:
@ -145,5 +159,5 @@ index 55579ecda80..b91afe4b22b 100644
params->result = E_FAIL;
return STATUS_SUCCESS;
--
2.30.2
2.34.1

View File

@ -1,562 +0,0 @@
From 503c347c96daf6d1f7be91038898a8b192fe5f6b Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Mon, 3 Nov 2014 02:06:40 +0000
Subject: [PATCH] winepulse: expose audio devices directly to programs
At present, winepulse only exposes one input device and one output device. This
patch adds support for individual audio devices, allowing (among other things)
the same program to record from two devices at the same time. It also brings
winepulse more in line with both winealsa et al. and Windows itself. The
moveable "Pulseaudio" devices are still present, and should presumably be
used by default.
Changes by Sebastian Lackner <sebastian@fds-team.de>:
* Merge functions set_device_guid and get_device_guid as they are always used together
* Fixed compiler warnings with -Werror
* Some style fixes and better error handling
* Move initialization code to pulse_test_connect()
Changes by Gabriel Ivăncescu <gabrielopcode@gmail.com>:
* Rebased with unixlib separation.
* Pass KEY_WOW64_64KEY so they use the same keys.
* Store the display name in the registry, and generate the GUID when enumerating.
* Move the special default devices lookup to get_pulse_name_by_guid.
---
dlls/winepulse.drv/mmdevdrv.c | 183 ++++++++++++++++++++++++++++------
dlls/winepulse.drv/pulse.c | 175 ++++++++++++++++++++++++++++++--
dlls/winepulse.drv/unixlib.h | 1 +
3 files changed, 318 insertions(+), 41 deletions(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index 35a66e1..c8856ff 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -134,6 +134,7 @@ struct ACImpl {
IUnknown *marshal;
IMMDevice *parent;
struct list entry;
+ char device[256];
float *vol;
LONG ref;
@@ -147,8 +148,6 @@ struct ACImpl {
AudioSessionWrapper *session_wrapper;
};
-static const WCHAR defaultW[] = L"PulseAudio";
-
static const IAudioClient3Vtbl AudioClient3_Vtbl;
static const IAudioRenderClientVtbl AudioRenderClient_Vtbl;
static const IAudioCaptureClientVtbl AudioCaptureClient_Vtbl;
@@ -267,39 +266,96 @@ static void set_stream_volumes(ACImpl *This)
pulse_call(set_volumes, &params);
}
-HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, const WCHAR ***ids, GUID **keys,
+HRESULT WINAPI AUDDRV_GetEndpointIDs(EDataFlow flow, WCHAR ***ids, GUID **keys,
UINT *num, UINT *def_index)
{
- WCHAR *id;
+ WCHAR flow_char = (flow == eRender) ? '0' : '1';
+ DWORD i, k = 0, count = 0, maxlen, size, type;
+ WCHAR *id, *key_name = NULL;
+ HKEY dev_key, key = NULL;
+ LSTATUS status;
+ GUID guid;
TRACE("%d %p %p %p\n", flow, ids, num, def_index);
- *num = 1;
+ *num = 0;
*def_index = 0;
-
- *ids = HeapAlloc(GetProcessHeap(), 0, sizeof(**ids));
+ *ids = NULL;
*keys = NULL;
- if (!*ids)
- return E_OUTOFMEMORY;
- (*ids)[0] = id = HeapAlloc(GetProcessHeap(), 0, sizeof(defaultW));
- *keys = HeapAlloc(GetProcessHeap(), 0, sizeof(**keys));
- if (!*keys || !id) {
- HeapFree(GetProcessHeap(), 0, id);
- HeapFree(GetProcessHeap(), 0, *keys);
- HeapFree(GetProcessHeap(), 0, *ids);
- *ids = NULL;
- *keys = NULL;
- return E_OUTOFMEMORY;
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Wine\\Drivers\\winepulse.drv\\devices",
+ 0, KEY_READ | KEY_WOW64_64KEY, &key) == ERROR_SUCCESS) {
+ status = RegQueryInfoKeyW(key, NULL, NULL, NULL, &count, &maxlen, NULL, NULL, NULL, NULL, NULL, NULL);
+ if (status != ERROR_SUCCESS || maxlen < 3)
+ count = 0;
}
- memcpy(id, defaultW, sizeof(defaultW));
- if (flow == eRender)
- (*keys)[0] = pulse_render_guid;
- else
- (*keys)[0] = pulse_capture_guid;
+ if (count && !(key_name = malloc((maxlen + 1) * sizeof(WCHAR))))
+ goto err;
+
+ *ids = HeapAlloc(GetProcessHeap(), 0, (count + 1) * sizeof(**ids));
+ *keys = HeapAlloc(GetProcessHeap(), 0, (count + 1) * sizeof(**keys));
+ if (!*ids || !*keys)
+ goto err;
+
+ if (!(id = HeapAlloc(GetProcessHeap(), 0, sizeof(L"PulseAudio"))))
+ goto err;
+ wcscpy(id, L"PulseAudio");
+ (*ids)[k] = id;
+ (*keys)[k++] = (flow == eRender) ? pulse_render_guid : pulse_capture_guid;
+
+ for (i = 0; i < count; i++) {
+ DWORD key_name_size = maxlen + 1;
+
+ if (RegEnumKeyExW(key, i, key_name, &key_name_size, NULL, NULL, NULL, NULL) != ERROR_SUCCESS ||
+ key_name_size < 3 || key_name[0] != flow_char ||
+ RegOpenKeyExW(key, key_name, 0, KEY_READ | KEY_WRITE | KEY_WOW64_64KEY, &dev_key) != ERROR_SUCCESS)
+ continue;
+
+ status = RegQueryValueExW(dev_key, L"name", 0, &type, NULL, &size);
+ if (status == ERROR_SUCCESS && type == REG_SZ && size >= sizeof(WCHAR)) {
+ if (!(id = HeapAlloc(GetProcessHeap(), 0, size))) {
+ RegCloseKey(dev_key);
+ goto err;
+ }
+ status = RegQueryValueExW(dev_key, L"name", 0, &type, (BYTE*)id, &size);
+ if (status == ERROR_SUCCESS && type == REG_SZ && size >= sizeof(WCHAR)) {
+ id[size / sizeof(WCHAR) - 1] = 0;
+
+ size = sizeof(guid);
+ status = RegQueryValueExW(dev_key, L"guid", 0, &type, (BYTE*)&guid, &size);
+
+ if (status != ERROR_SUCCESS || type != REG_BINARY || size != sizeof(guid)) {
+ CoCreateGuid(&guid);
+ status = RegSetValueExW(dev_key, L"guid", 0, REG_BINARY, (BYTE*)&guid, sizeof(guid));
+ if (status != ERROR_SUCCESS)
+ ERR("Failed to store device GUID for %s to registry\n", debugstr_w(key_name + 2));
+ }
+ (*ids)[k] = id;
+ (*keys)[k++] = guid;
+ } else {
+ HeapFree(GetProcessHeap(), 0, id);
+ }
+ }
+ RegCloseKey(dev_key);
+ }
+ *num = k;
+ *ids = HeapReAlloc(GetProcessHeap(), 0, *ids, k * sizeof(**ids));
+ *keys = HeapReAlloc(GetProcessHeap(), 0, *keys, k * sizeof(**keys));
+ if (key) RegCloseKey(key);
+ free(key_name);
return S_OK;
+
+err:
+ if (key) RegCloseKey(key);
+ while (k--) HeapFree(GetProcessHeap(), 0, (*ids)[k]);
+ HeapFree(GetProcessHeap(), 0, *keys);
+ HeapFree(GetProcessHeap(), 0, *ids);
+ free(key_name);
+ *ids = NULL;
+ *keys = NULL;
+ return E_OUTOFMEMORY;
}
int WINAPI AUDDRV_GetPriority(void)
@@ -314,26 +370,88 @@ int WINAPI AUDDRV_GetPriority(void)
return SUCCEEDED(params.result) ? Priority_Preferred : Priority_Unavailable;
}
+static BOOL get_pulse_name_by_guid(const GUID *guid, char *name, DWORD name_size, EDataFlow *flow)
+{
+ DWORD key_name_size;
+ WCHAR key_name[258];
+ DWORD index = 0;
+ HKEY key;
+
+ name[0] = 0;
+ if (IsEqualGUID(guid, &pulse_render_guid)) {
+ *flow = eRender;
+ return TRUE;
+ } else if (IsEqualGUID(guid, &pulse_capture_guid)) {
+ *flow = eCapture;
+ return TRUE;
+ }
+
+ if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Wine\\Drivers\\winepulse.drv\\devices",
+ 0, KEY_READ | KEY_WOW64_64KEY, &key) != ERROR_SUCCESS) {
+ ERR("No devices found in registry?\n");
+ return FALSE;
+ }
+
+ for (;;) {
+ DWORD size, type;
+ LSTATUS status;
+ GUID reg_guid;
+ HKEY dev_key;
+
+ key_name_size = ARRAY_SIZE(key_name);
+ if (RegEnumKeyExW(key, index++, key_name, &key_name_size, NULL,
+ NULL, NULL, NULL) != ERROR_SUCCESS)
+ break;
+
+ if (RegOpenKeyExW(key, key_name, 0, KEY_READ | KEY_WOW64_64KEY, &dev_key) != ERROR_SUCCESS) {
+ ERR("Couldn't open key: %s\n", wine_dbgstr_w(key_name));
+ continue;
+ }
+
+ size = sizeof(reg_guid);
+ status = RegQueryValueExW(dev_key, L"guid", 0, &type, (BYTE *)&reg_guid, &size);
+ RegCloseKey(dev_key);
+
+ if (status == ERROR_SUCCESS && type == REG_BINARY && size == sizeof(reg_guid) && IsEqualGUID(&reg_guid, guid)) {
+ RegCloseKey(key);
+
+ TRACE("Found matching device key: %s\n", wine_dbgstr_w(key_name));
+
+ if (key_name[0] == '0')
+ *flow = eRender;
+ else if (key_name[0] == '1')
+ *flow = eCapture;
+ else {
+ ERR("Unknown device type: %c\n", key_name[0]);
+ return FALSE;
+ }
+
+ return WideCharToMultiByte(CP_UNIXCP, 0, key_name + 2, -1, name, name_size, NULL, NULL);
+ }
+ }
+
+ RegCloseKey(key);
+ WARN("No matching device in registry for GUID %s\n", debugstr_guid(guid));
+ return FALSE;
+}
+
HRESULT WINAPI AUDDRV_GetAudioEndpoint(GUID *guid, IMMDevice *dev, IAudioClient **out)
{
- ACImpl *This;
+ ACImpl *This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
EDataFlow dataflow;
HRESULT hr;
TRACE("%s %p %p\n", debugstr_guid(guid), dev, out);
- if (IsEqualGUID(guid, &pulse_render_guid))
- dataflow = eRender;
- else if (IsEqualGUID(guid, &pulse_capture_guid))
- dataflow = eCapture;
- else
- return E_UNEXPECTED;
*out = NULL;
-
- This = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*This));
if (!This)
return E_OUTOFMEMORY;
+ if (!get_pulse_name_by_guid(guid, This->device, sizeof(This->device), &dataflow)) {
+ HeapFree(GetProcessHeap(), 0, This);
+ return AUDCLNT_E_DEVICE_INVALIDATED;
+ }
+
This->IAudioClient3_iface.lpVtbl = &AudioClient3_Vtbl;
This->IAudioRenderClient_iface.lpVtbl = &AudioRenderClient_Vtbl;
This->IAudioCaptureClient_iface.lpVtbl = &AudioCaptureClient_Vtbl;
@@ -609,6 +727,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
}
params.name = name = get_application_name();
+ params.device = This->device[0] ? This->device : NULL;
params.dataflow = This->dataflow;
params.mode = mode;
params.flags = flags;
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
index c8c3104..76e4935 100644
--- a/dlls/winepulse.drv/pulse.c
+++ b/dlls/winepulse.drv/pulse.c
@@ -82,6 +82,11 @@ typedef struct _ACPacket
UINT32 discont;
} ACPacket;
+typedef struct _PhysDevice {
+ struct list entry;
+ char device[0];
+} PhysDevice;
+
static pa_context *pulse_ctx;
static pa_mainloop *pulse_ml;
@@ -90,6 +95,9 @@ static WAVEFORMATEXTENSIBLE pulse_fmt[2];
static REFERENCE_TIME pulse_min_period[2], pulse_def_period[2];
static UINT g_phys_speakers_mask = 0;
+static struct list g_phys_speakers = LIST_INIT(g_phys_speakers);
+static struct list g_phys_sources = LIST_INIT(g_phys_sources);
+static HKEY devices_key;
static const REFERENCE_TIME MinimumPeriod = 30000;
static const REFERENCE_TIME DefaultPeriod = 100000;
@@ -153,6 +161,61 @@ static int muldiv(int a, int b, int c)
return ret;
}
+/* wrapper for NtCreateKey that creates the key recursively if necessary */
+static HKEY reg_create_key(HKEY root, const WCHAR *name, ULONG name_len)
+{
+ UNICODE_STRING nameW = { name_len, name_len, (WCHAR *)name };
+ OBJECT_ATTRIBUTES attr;
+ NTSTATUS status;
+ HANDLE ret = 0;
+
+ attr.Length = sizeof(attr);
+ attr.RootDirectory = root;
+ attr.ObjectName = &nameW;
+ attr.Attributes = 0;
+ attr.SecurityDescriptor = NULL;
+ attr.SecurityQualityOfService = NULL;
+
+ status = NtCreateKey(&ret, KEY_QUERY_VALUE | KEY_WRITE | KEY_WOW64_64KEY, &attr, 0, NULL, 0, NULL);
+ if (status == STATUS_OBJECT_NAME_NOT_FOUND) {
+ DWORD pos = 0, i = 0, len = name_len / sizeof(WCHAR);
+
+ /* don't try to create registry root */
+ if (!root) i += 10;
+
+ while (i < len && name[i] != '\\') i++;
+ if (i == len) return 0;
+ for (;;) {
+ nameW.Buffer = (WCHAR *)name + pos;
+ nameW.Length = (i - pos) * sizeof(WCHAR);
+ status = NtCreateKey(&ret, KEY_QUERY_VALUE | KEY_WRITE | KEY_WOW64_64KEY, &attr, 0, NULL, 0, NULL);
+
+ if (attr.RootDirectory != root) NtClose(attr.RootDirectory);
+ if (!NT_SUCCESS(status)) return 0;
+ if (i == len) break;
+ attr.RootDirectory = ret;
+ while (i < len && name[i] == '\\') i++;
+ pos = i;
+ while (i < len && name[i] != '\\') i++;
+ }
+ }
+ return ret;
+}
+
+static HKEY open_devices_key(void)
+{
+ static const WCHAR drv_key_devicesW[] = {
+ '\\','R','e','g','i','s','t','r','y','\\','M','a','c','h','i','n','e','\\',
+ 'S','o','f','t','w','a','r','e','\\','W','i','n','e','\\','D','r','i','v','e','r','s','\\',
+ 'w','i','n','e','p','u','l','s','e','.','d','r','v','\\','d','e','v','i','c','e','s'
+ };
+ HANDLE ret;
+
+ if (!(ret = reg_create_key(NULL, drv_key_devicesW, sizeof(drv_key_devicesW))))
+ ERR("Failed to open devices registry key\n");
+ return ret;
+}
+
/* Following pulseaudio design here, mainloop has the lock taken whenever
* it is handling something for pulse, and the lock is required whenever
* doing any pa_* call that can affect the state in any way
@@ -191,6 +254,13 @@ static NTSTATUS pulse_process_attach(void *args)
static NTSTATUS pulse_process_detach(void *args)
{
+ PhysDevice *dev, *dev_next;
+
+ LIST_FOR_EACH_ENTRY_SAFE(dev, dev_next, &g_phys_speakers, PhysDevice, entry)
+ free(dev);
+ LIST_FOR_EACH_ENTRY_SAFE(dev, dev_next, &g_phys_sources, PhysDevice, entry)
+ free(dev);
+
if (pulse_ctx)
{
pa_context_disconnect(pulse_ctx);
@@ -358,12 +428,73 @@ static DWORD pulse_channel_map_to_channel_mask(const pa_channel_map *map)
return mask;
}
-/* For default PulseAudio render device, OR together all of the
- * PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
+static void store_device_info(EDataFlow flow, const char *device, const char *name)
+{
+ static const WCHAR nameW[] = { 'n','a','m','e' };
+ UNICODE_STRING name_str = { sizeof(nameW), sizeof(nameW), (WCHAR*)nameW };
+ UINT name_len = strlen(name);
+ WCHAR key_name[258], *wname;
+ DWORD len, key_len;
+ HKEY key;
+
+ if (!devices_key || !(wname = malloc((name_len + 1) * sizeof(WCHAR))))
+ return;
+
+ key_name[0] = (flow == eCapture) ? '1' : '0';
+ key_name[1] = ',';
+
+ key_len = ntdll_umbstowcs(device, strlen(device), key_name + 2, ARRAY_SIZE(key_name) - 2);
+ if (!key_len || key_len >= ARRAY_SIZE(key_name) - 2)
+ goto done;
+ key_len += 2;
+
+ if (!(len = ntdll_umbstowcs(name, name_len, wname, name_len)))
+ goto done;
+ wname[len] = 0;
+
+ if (!(key = reg_create_key(devices_key, key_name, key_len * sizeof(WCHAR)))) {
+ ERR("Failed to open registry key for device %s\n", device);
+ goto done;
+ }
+
+ if (NtSetValueKey(key, &name_str, 0, REG_SZ, wname, (len + 1) * sizeof(WCHAR)))
+ ERR("Failed to store name for %s to registry\n", device);
+ NtClose(key);
+
+done:
+ free(wname);
+}
+
+static void pulse_add_device(struct list *list, const char *device)
+{
+ DWORD len = strlen(device);
+ PhysDevice *dev = malloc(offsetof(PhysDevice, device[len + 1]));
+
+ if (!dev)
+ return;
+ memcpy(dev->device, device, len + 1);
+
+ list_add_tail(list, &dev->entry);
+}
+
static void pulse_phys_speakers_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
{
- if (i)
+ if (i && i->name && i->name[0]) {
+ /* For default PulseAudio render device, OR together all of the
+ * PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
g_phys_speakers_mask |= pulse_channel_map_to_channel_mask(&i->channel_map);
+
+ store_device_info(eRender, i->name, i->description);
+ pulse_add_device(&g_phys_speakers, i->name);
+ }
+}
+
+static void pulse_phys_sources_cb(pa_context *c, const pa_source_info *i, int eol, void *userdata)
+{
+ if (i && i->name && i->name[0]) {
+ store_device_info(eCapture, i->name, i->description);
+ pulse_add_device(&g_phys_sources, i->name);
+ }
}
/* For most hardware on Windows, users must choose a configuration with an even
@@ -541,6 +672,11 @@ static NTSTATUS pulse_test_connect(void *args)
pa_context *ctx;
pulse_lock();
+
+ /* Make sure we never run twice accidentally */
+ if (!list_empty(&g_phys_speakers))
+ goto success;
+
ml = pa_mainloop_new();
pa_mainloop_set_poll_func(ml, pulse_poll_func, NULL);
@@ -581,7 +717,12 @@ static NTSTATUS pulse_test_connect(void *args)
pulse_probe_settings(ml, ctx, 1, &pulse_fmt[0]);
pulse_probe_settings(ml, ctx, 0, &pulse_fmt[1]);
+ devices_key = open_devices_key();
g_phys_speakers_mask = 0;
+
+ pulse_add_device(&g_phys_speakers, "");
+ pulse_add_device(&g_phys_sources, "");
+
o = pa_context_get_sink_info_list(ctx, &pulse_phys_speakers_cb, NULL);
if (o) {
while (pa_mainloop_iterate(ml, 1, &ret) >= 0 &&
@@ -590,6 +731,15 @@ static NTSTATUS pulse_test_connect(void *args)
pa_operation_unref(o);
}
+ o = pa_context_get_source_info_list(ctx, &pulse_phys_sources_cb, NULL);
+ if (o) {
+ while (pa_mainloop_iterate(ml, 1, &ret) >= 0 &&
+ pa_operation_get_state(o) == PA_OPERATION_RUNNING)
+ {}
+ pa_operation_unref(o);
+ }
+ NtClose(devices_key);
+
pa_context_unref(ctx);
pa_mainloop_free(ml);
@@ -601,6 +751,7 @@ static NTSTATUS pulse_test_connect(void *args)
config->modes[1].def_period = pulse_def_period[1];
config->modes[1].min_period = pulse_min_period[1];
+success:
pulse_unlock();
params->result = S_OK;
@@ -769,12 +920,13 @@ static HRESULT pulse_spec_from_waveformat(struct pulse_stream *stream, const WAV
return S_OK;
}
-static HRESULT pulse_stream_connect(struct pulse_stream *stream, UINT32 period_bytes)
+static HRESULT pulse_stream_connect(struct pulse_stream *stream, const char *device, UINT32 period_bytes)
{
int ret;
char buffer[64];
static LONG number;
pa_buffer_attr attr;
+ int moving = 0;
ret = InterlockedIncrement(&number);
sprintf(buffer, "audio stream #%i", ret);
@@ -795,12 +947,17 @@ static HRESULT pulse_stream_connect(struct pulse_stream *stream, UINT32 period_b
attr.maxlength = stream->bufsize_frames * pa_frame_size(&stream->ss);
attr.prebuf = pa_frame_size(&stream->ss);
dump_attr(&attr);
+
+ /* If device name is given use exactly the specified device */
+ if (device)
+ moving = PA_STREAM_DONT_MOVE;
+
if (stream->dataflow == eRender)
- ret = pa_stream_connect_playback(stream->stream, NULL, &attr,
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY, NULL, NULL);
+ ret = pa_stream_connect_playback(stream->stream, device, &attr,
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY|moving, NULL, NULL);
else
- ret = pa_stream_connect_record(stream->stream, NULL, &attr,
- PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY);
+ ret = pa_stream_connect_record(stream->stream, device, &attr,
+ PA_STREAM_START_CORKED|PA_STREAM_START_UNMUTED|PA_STREAM_ADJUST_LATENCY|moving);
if (ret < 0) {
WARN("Returns %i\n", ret);
return AUDCLNT_E_ENDPOINT_CREATE_FAILED;
@@ -862,7 +1019,7 @@ static NTSTATUS pulse_create_stream(void *args)
stream->share = params->mode;
stream->flags = params->flags;
- hr = pulse_stream_connect(stream, 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);
diff --git a/dlls/winepulse.drv/unixlib.h b/dlls/winepulse.drv/unixlib.h
index d28a73c..5445a0f 100644
--- a/dlls/winepulse.drv/unixlib.h
+++ b/dlls/winepulse.drv/unixlib.h
@@ -40,6 +40,7 @@ struct main_loop_params
struct create_stream_params
{
const char *name;
+ const char *device;
EDataFlow dataflow;
AUDCLNT_SHAREMODE mode;
DWORD flags;
--
2.28.0

View File

@ -1,333 +0,0 @@
From d5ab784623b3ea451cf2ceca466662e320958ede Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Thu, 4 Dec 2014 21:36:42 +0000
Subject: [PATCH] winepulse: implement GetPropValue
Changes by Gabriel Ivăncescu <gabrielopcode@gmail.com>:
* Rebased with unixlib separation.
* Cache the pulse device names for a given GUID.
---
dlls/winepulse.drv/mmdevdrv.c | 92 ++++++++++++++++++++++++++++++++++-
dlls/winepulse.drv/pulse.c | 69 ++++++++++++++++++++++++--
dlls/winepulse.drv/unixlib.h | 18 +++++++
3 files changed, 173 insertions(+), 6 deletions(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index c8856ff..072d27e 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -63,6 +63,14 @@ static struct pulse_config pulse_config;
static HANDLE pulse_thread;
static struct list g_sessions = LIST_INIT(g_sessions);
+static struct list g_devices_cache = LIST_INIT(g_devices_cache);
+
+struct device_cache {
+ struct list entry;
+ GUID guid;
+ EDataFlow dataflow;
+ char device[0];
+};
static GUID pulse_render_guid =
{ 0xfd47d9cc, 0x4218, 0x4135, { 0x9c, 0xe2, 0x0c, 0x19, 0x5c, 0x87, 0x40, 0x5b } };
@@ -88,6 +96,10 @@ BOOL WINAPI DllMain(HINSTANCE dll, DWORD reason, void *reserved)
if (__wine_unix_call(pulse_handle, process_attach, NULL))
return FALSE;
} else if (reason == DLL_PROCESS_DETACH) {
+ struct device_cache *device, *device_next;
+
+ LIST_FOR_EACH_ENTRY_SAFE(device, device_next, &g_devices_cache, struct device_cache, entry)
+ free(device);
__wine_unix_call(pulse_handle, process_detach, NULL);
if (pulse_thread) {
WaitForSingleObject(pulse_thread, INFINITE);
@@ -372,6 +384,7 @@ int WINAPI AUDDRV_GetPriority(void)
static BOOL get_pulse_name_by_guid(const GUID *guid, char *name, DWORD name_size, EDataFlow *flow)
{
+ struct device_cache *device;
DWORD key_name_size;
WCHAR key_name[258];
DWORD index = 0;
@@ -386,6 +399,15 @@ static BOOL get_pulse_name_by_guid(const GUID *guid, char *name, DWORD name_size
return TRUE;
}
+ /* Check the cache first */
+ LIST_FOR_EACH_ENTRY(device, &g_devices_cache, struct device_cache, entry) {
+ if (!IsEqualGUID(guid, &device->guid))
+ continue;
+ *flow = device->dataflow;
+ strcpy(name, device->device);
+ return TRUE;
+ }
+
if (RegOpenKeyExW(HKEY_LOCAL_MACHINE, L"Software\\Wine\\Drivers\\winepulse.drv\\devices",
0, KEY_READ | KEY_WOW64_64KEY, &key) != ERROR_SUCCESS) {
ERR("No devices found in registry?\n");
@@ -397,6 +419,7 @@ static BOOL get_pulse_name_by_guid(const GUID *guid, char *name, DWORD name_size
LSTATUS status;
GUID reg_guid;
HKEY dev_key;
+ int len;
key_name_size = ARRAY_SIZE(key_name);
if (RegEnumKeyExW(key, index++, key_name, &key_name_size, NULL,
@@ -426,7 +449,17 @@ static BOOL get_pulse_name_by_guid(const GUID *guid, char *name, DWORD name_size
return FALSE;
}
- return WideCharToMultiByte(CP_UNIXCP, 0, key_name + 2, -1, name, name_size, NULL, NULL);
+ if (!(len = WideCharToMultiByte(CP_UNIXCP, 0, key_name + 2, -1, name, name_size, NULL, NULL)))
+ return FALSE;
+
+ device = malloc(offsetof(struct device_cache, device[len]));
+ if (device) {
+ device->guid = reg_guid;
+ device->dataflow = *flow;
+ strcpy(device->device, name);
+ list_add_tail(&g_devices_cache, &device->entry);
+ }
+ return TRUE;
}
}
@@ -2491,8 +2524,49 @@ HRESULT WINAPI AUDDRV_GetAudioSessionManager(IMMDevice *device,
return S_OK;
}
+static HRESULT get_device_path(struct get_device_info_params *params, GUID *guid, PROPVARIANT *out)
+{
+ UINT serial_number;
+ const WCHAR *fmt;
+ WCHAR path[128];
+ int len;
+
+ switch (params->bus_type) {
+ case phys_device_bus_pci:
+ fmt = L"{1}.HDAUDIO\\FUNC_01&VEN_%04X&DEV_%04X\\%u&%08X";
+ break;
+ case phys_device_bus_usb:
+ fmt = L"{1}.USB\\VID_%04X&PID_%04X\\%u&%08X";
+ break;
+ default:
+ return E_FAIL;
+ }
+
+ /* As hardly any audio devices have serial numbers, Windows instead
+ appears to use a persistent random number. We emulate this here
+ by instead using the last 8 hex digits of the GUID. */
+ serial_number = (guid->Data4[4] << 24) | (guid->Data4[5] << 16) | (guid->Data4[6] << 8) | guid->Data4[7];
+
+ len = swprintf(path, ARRAY_SIZE(path), fmt, params->vendor_id, params->product_id, params->index, serial_number);
+ if (len < 0)
+ return E_FAIL;
+
+ out->vt = VT_LPWSTR;
+ out->pwszVal = CoTaskMemAlloc((len + 1) * sizeof(WCHAR));
+ if (!out->pwszVal)
+ return E_OUTOFMEMORY;
+
+ wcscpy(out->pwszVal, path);
+ return S_OK;
+}
+
HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARIANT *out)
{
+ static const PROPERTYKEY devicepath_key = { /* undocumented? - {b3f8fa53-0004-438e-9003-51a46e139bfc},2 */
+ {0xb3f8fa53, 0x0004, 0x438e, {0x90, 0x03, 0x51, 0xa4, 0x6e, 0x13, 0x9b, 0xfc}}, 2
+ };
+ struct get_device_info_params params;
+
TRACE("%s, (%s,%u), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out);
if (IsEqualGUID(guid, &pulse_render_guid) && IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
@@ -2502,5 +2576,21 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
return out->ulVal ? S_OK : E_FAIL;
}
+ if (!get_pulse_name_by_guid(guid, params.device, sizeof(params.device), &params.dataflow))
+ return E_FAIL;
+
+ pulse_call(get_device_info, &params);
+ if (params.result != S_OK)
+ return params.result;
+
+ if (IsEqualPropertyKey(*prop, devicepath_key))
+ return get_device_path(&params, guid, out);
+
+ if (IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_FormFactor)) {
+ out->vt = VT_UI4;
+ out->ulVal = params.form;
+ return S_OK;
+ }
+
return E_NOTIMPL;
}
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
index 76e4935..951a7bf 100644
--- a/dlls/winepulse.drv/pulse.c
+++ b/dlls/winepulse.drv/pulse.c
@@ -84,6 +84,10 @@ typedef struct _ACPacket
typedef struct _PhysDevice {
struct list entry;
+ enum phys_device_bus_type bus_type;
+ USHORT vendor_id, product_id;
+ EndpointFormFactor form;
+ UINT index;
char device[0];
} PhysDevice;
@@ -465,7 +469,33 @@ done:
free(wname);
}
-static void pulse_add_device(struct list *list, const char *device)
+static void fill_device_info(PhysDevice *dev, pa_proplist *p)
+{
+ const char *buffer;
+
+ dev->bus_type = phys_device_bus_invalid;
+ dev->vendor_id = 0;
+ dev->product_id = 0;
+
+ if (!p)
+ return;
+
+ if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_BUS))) {
+ if (!strcmp(buffer, "usb"))
+ dev->bus_type = phys_device_bus_usb;
+ else if (!strcmp(buffer, "pci"))
+ dev->bus_type = phys_device_bus_pci;
+ }
+
+ if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_VENDOR_ID)))
+ dev->vendor_id = strtol(buffer, NULL, 16);
+
+ if ((buffer = pa_proplist_gets(p, PA_PROP_DEVICE_PRODUCT_ID)))
+ dev->product_id = strtol(buffer, NULL, 16);
+}
+
+static void pulse_add_device(struct list *list, pa_proplist *proplist, int index, EndpointFormFactor form,
+ const char *device)
{
DWORD len = strlen(device);
PhysDevice *dev = malloc(offsetof(PhysDevice, device[len + 1]));
@@ -473,6 +503,9 @@ static void pulse_add_device(struct list *list, const char *device)
if (!dev)
return;
memcpy(dev->device, device, len + 1);
+ dev->form = form;
+ dev->index = index;
+ fill_device_info(dev, proplist);
list_add_tail(list, &dev->entry);
}
@@ -485,7 +518,7 @@ static void pulse_phys_speakers_cb(pa_context *c, const pa_sink_info *i, int eol
g_phys_speakers_mask |= pulse_channel_map_to_channel_mask(&i->channel_map);
store_device_info(eRender, i->name, i->description);
- pulse_add_device(&g_phys_speakers, i->name);
+ pulse_add_device(&g_phys_speakers, i->proplist, i->index, Speakers, i->name);
}
}
@@ -493,7 +526,8 @@ static void pulse_phys_sources_cb(pa_context *c, const pa_source_info *i, int eo
{
if (i && i->name && i->name[0]) {
store_device_info(eCapture, i->name, i->description);
- pulse_add_device(&g_phys_sources, i->name);
+ pulse_add_device(&g_phys_sources, i->proplist, i->index,
+ (i->monitor_of_sink == PA_INVALID_INDEX) ? Microphone : LineLevel, i->name);
}
}
@@ -720,8 +754,8 @@ static NTSTATUS pulse_test_connect(void *args)
devices_key = open_devices_key();
g_phys_speakers_mask = 0;
- pulse_add_device(&g_phys_speakers, "");
- pulse_add_device(&g_phys_sources, "");
+ pulse_add_device(&g_phys_speakers, NULL, 0, Speakers, "");
+ pulse_add_device(&g_phys_sources, NULL, 0, Microphone, "");
o = pa_context_get_sink_info_list(ctx, &pulse_phys_speakers_cb, NULL);
if (o) {
@@ -765,6 +799,30 @@ fail:
return STATUS_SUCCESS;
}
+static NTSTATUS pulse_get_device_info(void *args)
+{
+ struct get_device_info_params *params = args;
+ const struct list *const list = (params->dataflow == eRender) ? &g_phys_speakers : &g_phys_sources;
+ const char *device = params->device;
+ PhysDevice *dev;
+
+ LIST_FOR_EACH_ENTRY(dev, list, PhysDevice, entry) {
+ if (!strcmp(device, dev->device)) {
+ params->bus_type = dev->bus_type;
+ params->vendor_id = dev->vendor_id;
+ params->product_id = dev->product_id;
+ params->index = dev->index;
+ params->form = dev->form;
+ params->result = S_OK;
+ return STATUS_SUCCESS;
+ }
+ }
+
+ WARN("Unknown device %s\n", device);
+ params->result = E_FAIL;
+ return STATUS_SUCCESS;
+}
+
static DWORD get_channel_mask(unsigned int channels)
{
switch(channels) {
@@ -2139,5 +2197,6 @@ const unixlib_entry_t __wine_unix_call_funcs[] =
pulse_set_volumes,
pulse_set_event_handle,
pulse_test_connect,
+ pulse_get_device_info,
pulse_is_started,
};
diff --git a/dlls/winepulse.drv/unixlib.h b/dlls/winepulse.drv/unixlib.h
index 5445a0f..7383110 100644
--- a/dlls/winepulse.drv/unixlib.h
+++ b/dlls/winepulse.drv/unixlib.h
@@ -181,6 +181,23 @@ struct test_connect_params
struct pulse_config *config;
};
+enum phys_device_bus_type {
+ phys_device_bus_invalid = -1,
+ phys_device_bus_pci,
+ phys_device_bus_usb
+};
+
+struct get_device_info_params
+{
+ char device[256];
+ EDataFlow dataflow;
+ enum phys_device_bus_type bus_type;
+ USHORT vendor_id, product_id;
+ EndpointFormFactor form;
+ UINT index;
+ HRESULT result;
+};
+
struct is_started_params
{
struct pulse_stream *stream;
@@ -211,5 +228,6 @@ enum unix_funcs
set_volumes,
set_event_handle,
test_connect,
+ get_device_info,
is_started,
};
--
2.30.2

View File

@ -1,183 +0,0 @@
From 5b1db5456a018cc39938effae3c1bf05bd7618f9 Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Sun, 21 Dec 2014 23:49:41 +0000
Subject: [PATCH] winepulse: fetch actual program name if possible
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Changes by Sebastian Lackner <sebastian@fds-team.de>:
* Improved error handling, fix memory leak
* Remove check for UTF16, there are several examples where this doesn't work
(for example with VLC media player)
* Simplify algorithm to choose best translation.
Changes by Gabriel Ivăncescu <gabrielopcode@gmail.com>:
* Move the bulk of it into get_application_name, since it needs the path.
* Pass an argument to query the program name or not, to avoid querying it
during test_connect, so it matches the previous behavior.
---
dlls/winepulse.drv/Makefile.in | 2 +-
dlls/winepulse.drv/mmdevdrv.c | 107 +++++++++++++++++++++++++++++++--
2 files changed, 104 insertions(+), 5 deletions(-)
diff --git a/dlls/winepulse.drv/Makefile.in b/dlls/winepulse.drv/Makefile.in
index c71b2833d13..d4b40e66644 100644
--- a/dlls/winepulse.drv/Makefile.in
+++ b/dlls/winepulse.drv/Makefile.in
@@ -1,7 +1,7 @@
EXTRADEFS = -DWINE_NO_LONG_TYPES
MODULE = winepulse.drv
UNIXLIB = winepulse.so
-IMPORTS = dxguid uuid winmm user32 advapi32 ole32
+IMPORTS = dxguid uuid winmm user32 advapi32 ole32 version
EXTRALIBS = $(PULSE_LIBS) $(PTHREAD_LIBS) -lm
EXTRAINCL = $(PULSE_CFLAGS)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index 072d27e16ac..3559baf7a80 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -30,6 +30,7 @@
#include "wine/list.h"
#include "ole2.h"
+#include "mimeole.h"
#include "dshow.h"
#include "dsound.h"
#include "propsys.h"
@@ -240,13 +241,111 @@ static DWORD CALLBACK pulse_mainloop_thread(void *event)
return 0;
}
-static char *get_application_name(void)
+typedef struct tagLANGANDCODEPAGE
+{
+ WORD wLanguage;
+ WORD wCodePage;
+} LANGANDCODEPAGE;
+
+static BOOL query_productname(void *data, LANGANDCODEPAGE *lang, LPVOID *buffer, DWORD *len)
+{
+ WCHAR pn[37];
+ swprintf(pn, ARRAY_SIZE(pn), L"\\StringFileInfo\\%04x%04x\\ProductName", lang->wLanguage, lang->wCodePage);
+ return VerQueryValueW(data, pn, buffer, len) && *len;
+}
+
+static char *get_application_name(BOOL query_program_name)
{
WCHAR path[MAX_PATH], *name;
+ char *str = NULL;
size_t len;
- char *str;
GetModuleFileNameW(NULL, path, ARRAY_SIZE(path));
+
+ if (query_program_name)
+ {
+ UINT translate_size, productname_size;
+ LANGANDCODEPAGE *translate;
+ LPVOID productname;
+ BOOL found = FALSE;
+ void *data = NULL;
+ unsigned int i;
+ LCID locale;
+ DWORD size;
+
+ size = GetFileVersionInfoSizeW(path, NULL);
+ if (!size)
+ goto skip;
+
+ data = malloc(size);
+ if (!data)
+ goto skip;
+
+ if (!GetFileVersionInfoW(path, 0, size, data))
+ goto skip;
+
+ if (!VerQueryValueW(data, L"\\VarFileInfo\\Translation", (LPVOID *)&translate, &translate_size))
+ goto skip;
+
+ /* no translations found */
+ if (translate_size < sizeof(LANGANDCODEPAGE))
+ goto skip;
+
+ /* The following code will try to find the best translation. We first search for an
+ * exact match of the language, then a match of the language PRIMARYLANGID, then we
+ * search for a LANG_NEUTRAL match, and if that still doesn't work we pick the
+ * first entry which contains a proper productname. */
+
+ locale = GetThreadLocale();
+
+ for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); i++) {
+ if (translate[i].wLanguage == locale &&
+ query_productname(data, &translate[i], &productname, &productname_size)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (!found) {
+ for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); i++) {
+ if (PRIMARYLANGID(translate[i].wLanguage) == PRIMARYLANGID(locale) &&
+ query_productname(data, &translate[i], &productname, &productname_size)) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); i++) {
+ if (PRIMARYLANGID(translate[i].wLanguage) == LANG_NEUTRAL &&
+ query_productname(data, &translate[i], &productname, &productname_size)) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (!found) {
+ for (i = 0; i < translate_size / sizeof(LANGANDCODEPAGE); i++) {
+ if (query_productname(data, &translate[i], &productname, &productname_size)) {
+ found = TRUE;
+ break;
+ }
+ }
+ }
+
+ if (found) {
+ len = WideCharToMultiByte(CP_UTF8, 0, productname, -1, NULL, 0, NULL, NULL);
+ str = malloc(len);
+ if (str) WideCharToMultiByte(CP_UTF8, 0, productname, -1, str, len, NULL, NULL);
+ }
+
+ skip:
+ free(data);
+ if (str) return str;
+ }
+
name = wcsrchr(path, '\\');
if (!name)
name = path;
@@ -375,7 +474,7 @@ int WINAPI AUDDRV_GetPriority(void)
struct test_connect_params params;
char *name;
- params.name = name = get_application_name();
+ params.name = name = get_application_name(FALSE);
params.config = &pulse_config;
pulse_call(test_connect, &params);
free(name);
@@ -759,7 +858,7 @@ static HRESULT WINAPI AudioClient_Initialize(IAudioClient3 *iface,
CloseHandle(event);
}
- params.name = name = get_application_name();
+ params.name = name = get_application_name(TRUE);
params.device = This->device[0] ? This->device : NULL;
params.dataflow = This->dataflow;
params.mode = mode;
--
2.34.1

View File

@ -1,167 +0,0 @@
From 5eea4a95306f510d6056cdb79faaed73a84e53dd Mon Sep 17 00:00:00 2001
From: Mark Harmstone <mark@harmstone.com>
Date: Wed, 10 Dec 2014 18:08:41 +0000
Subject: [PATCH] winepulse: return PKEY_AudioEndpoint_PhysicalSpeakers device
prop
Changes by Sebastian Lackner <sebastian@fds-team.de>:
* Rework logic to get all channel masks in pulse_test_connect.
Changes by Gabriel Ivăncescu <gabrielopcode@gmail.com>:
* Rebased with unixlib separation.
---
dlls/winepulse.drv/mmdevdrv.c | 13 ++++++-------
dlls/winepulse.drv/pulse.c | 24 +++++++++++++++---------
dlls/winepulse.drv/unixlib.h | 2 +-
3 files changed, 22 insertions(+), 17 deletions(-)
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index 3559baf..a29450e 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -2668,13 +2668,6 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
TRACE("%s, (%s,%u), %p\n", wine_dbgstr_guid(guid), wine_dbgstr_guid(&prop->fmtid), prop->pid, out);
- if (IsEqualGUID(guid, &pulse_render_guid) && IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
- out->vt = VT_UI4;
- out->ulVal = pulse_config.speakers_mask;
-
- return out->ulVal ? S_OK : E_FAIL;
- }
-
if (!get_pulse_name_by_guid(guid, params.device, sizeof(params.device), &params.dataflow))
return E_FAIL;
@@ -2691,5 +2684,11 @@ HRESULT WINAPI AUDDRV_GetPropValue(GUID *guid, const PROPERTYKEY *prop, PROPVARI
return S_OK;
}
+ if (IsEqualPropertyKey(*prop, PKEY_AudioEndpoint_PhysicalSpeakers)) {
+ out->vt = VT_UI4;
+ out->ulVal = params.channel_mask;
+ return out->ulVal ? S_OK : E_FAIL;
+ }
+
return E_NOTIMPL;
}
diff --git a/dlls/winepulse.drv/pulse.c b/dlls/winepulse.drv/pulse.c
index 951a7bf..79c676f 100644
--- a/dlls/winepulse.drv/pulse.c
+++ b/dlls/winepulse.drv/pulse.c
@@ -87,6 +87,7 @@ typedef struct _PhysDevice {
enum phys_device_bus_type bus_type;
USHORT vendor_id, product_id;
EndpointFormFactor form;
+ DWORD channel_mask;
UINT index;
char device[0];
} PhysDevice;
@@ -98,7 +99,6 @@ static pa_mainloop *pulse_ml;
static WAVEFORMATEXTENSIBLE pulse_fmt[2];
static REFERENCE_TIME pulse_min_period[2], pulse_def_period[2];
-static UINT g_phys_speakers_mask = 0;
static struct list g_phys_speakers = LIST_INIT(g_phys_speakers);
static struct list g_phys_sources = LIST_INIT(g_phys_sources);
static HKEY devices_key;
@@ -495,7 +495,7 @@ static void fill_device_info(PhysDevice *dev, pa_proplist *p)
}
static void pulse_add_device(struct list *list, pa_proplist *proplist, int index, EndpointFormFactor form,
- const char *device)
+ DWORD channel_mask, const char *device)
{
DWORD len = strlen(device);
PhysDevice *dev = malloc(offsetof(PhysDevice, device[len + 1]));
@@ -505,6 +505,7 @@ static void pulse_add_device(struct list *list, pa_proplist *proplist, int index
memcpy(dev->device, device, len + 1);
dev->form = form;
dev->index = index;
+ dev->channel_mask = channel_mask;
fill_device_info(dev, proplist);
list_add_tail(list, &dev->entry);
@@ -512,13 +513,19 @@ static void pulse_add_device(struct list *list, pa_proplist *proplist, int index
static void pulse_phys_speakers_cb(pa_context *c, const pa_sink_info *i, int eol, void *userdata)
{
+ struct list *speaker;
+
if (i && i->name && i->name[0]) {
+ DWORD channel_mask = pulse_channel_map_to_channel_mask(&i->channel_map);
+
/* For default PulseAudio render device, OR together all of the
* PKEY_AudioEndpoint_PhysicalSpeakers values of the sinks. */
- g_phys_speakers_mask |= pulse_channel_map_to_channel_mask(&i->channel_map);
+ speaker = list_head(&g_phys_speakers);
+ if (speaker)
+ LIST_ENTRY(speaker, PhysDevice, entry)->channel_mask |= channel_mask;
store_device_info(eRender, i->name, i->description);
- pulse_add_device(&g_phys_speakers, i->proplist, i->index, Speakers, i->name);
+ pulse_add_device(&g_phys_speakers, i->proplist, i->index, Speakers, channel_mask, i->name);
}
}
@@ -527,7 +534,7 @@ static void pulse_phys_sources_cb(pa_context *c, const pa_source_info *i, int eo
if (i && i->name && i->name[0]) {
store_device_info(eCapture, i->name, i->description);
pulse_add_device(&g_phys_sources, i->proplist, i->index,
- (i->monitor_of_sink == PA_INVALID_INDEX) ? Microphone : LineLevel, i->name);
+ (i->monitor_of_sink == PA_INVALID_INDEX) ? Microphone : LineLevel, 0, i->name);
}
}
@@ -752,10 +759,9 @@ static NTSTATUS pulse_test_connect(void *args)
pulse_probe_settings(ml, ctx, 0, &pulse_fmt[1]);
devices_key = open_devices_key();
- g_phys_speakers_mask = 0;
- pulse_add_device(&g_phys_speakers, NULL, 0, Speakers, "");
- pulse_add_device(&g_phys_sources, NULL, 0, Microphone, "");
+ pulse_add_device(&g_phys_speakers, NULL, 0, Speakers, 0, "");
+ pulse_add_device(&g_phys_sources, NULL, 0, Microphone, 0, "");
o = pa_context_get_sink_info_list(ctx, &pulse_phys_speakers_cb, NULL);
if (o) {
@@ -777,7 +783,6 @@ static NTSTATUS pulse_test_connect(void *args)
pa_context_unref(ctx);
pa_mainloop_free(ml);
- config->speakers_mask = g_phys_speakers_mask;
config->modes[0].format = pulse_fmt[0];
config->modes[0].def_period = pulse_def_period[0];
config->modes[0].min_period = pulse_min_period[0];
@@ -813,6 +818,7 @@ static NTSTATUS pulse_get_device_info(void *args)
params->product_id = dev->product_id;
params->index = dev->index;
params->form = dev->form;
+ params->channel_mask = dev->channel_mask;
params->result = S_OK;
return STATUS_SUCCESS;
}
diff --git a/dlls/winepulse.drv/unixlib.h b/dlls/winepulse.drv/unixlib.h
index 7383110..9cd73a8 100644
--- a/dlls/winepulse.drv/unixlib.h
+++ b/dlls/winepulse.drv/unixlib.h
@@ -29,7 +29,6 @@ struct pulse_config
REFERENCE_TIME def_period;
REFERENCE_TIME min_period;
} modes[2];
- unsigned int speakers_mask;
};
struct main_loop_params
@@ -194,6 +193,7 @@ struct get_device_info_params
enum phys_device_bus_type bus_type;
USHORT vendor_id, product_id;
EndpointFormFactor form;
+ DWORD channel_mask;
UINT index;
HRESULT result;
};
--
2.30.2

View File

@ -1,4 +1,4 @@
From e8ad0fb2501a0ebd489534dbf7f89af209f972bc Mon Sep 17 00:00:00 2001
From 8f500bf79ec01cee5683a3614428662ac29e8e4d Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Sat, 16 May 2015 03:16:15 +0200
Subject: [PATCH] wininet: Replacing header fields should fail if they do not
@ -8,27 +8,31 @@ A lot of details are not properly covered by tests yet and were
marked with FIXME comments. The implementation was written in such
a way that it behaves identical to the old code in such situations.
---
dlls/wininet/http.c | 185 ++++++++++++++++++++++----------------------
1 file changed, 93 insertions(+), 92 deletions(-)
dlls/wininet/http.c | 205 ++++++++++++++++++++++----------------------
1 file changed, 103 insertions(+), 102 deletions(-)
diff --git a/dlls/wininet/http.c b/dlls/wininet/http.c
index ec984441399..98f63a8c0a4 100644
index 1cc688b6b07..1219507bd3d 100644
--- a/dlls/wininet/http.c
+++ b/dlls/wininet/http.c
@@ -6120,127 +6120,128 @@ static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer)
@@ -6117,130 +6117,131 @@ static LPWSTR * HTTP_InterpretHttpHeader(LPCWSTR buffer)
static DWORD HTTP_ProcessHeader(http_request_t *request, LPCWSTR field, LPCWSTR value, DWORD dwModifier)
{
- LPHTTPHEADERW lphttpHdr = NULL;
+ LPHTTPHEADERW lphttpHdr;
INT index;
BOOL request_only = !!(dwModifier & HTTP_ADDHDR_FLAG_REQ);
- INT index;
- BOOL request_only = !!(dwModifier & HTTP_ADDHDR_FLAG_REQ);
- DWORD res = ERROR_HTTP_INVALID_HEADER;
+ LPHTTPHEADERW lphttpHdr;
+ INT index;
+ BOOL request_only = !!(dwModifier & HTTP_ADDHDR_FLAG_REQ);
+ DWORD res = ERROR_SUCCESS;
TRACE("--> %s: %s - 0x%08x\n", debugstr_w(field), debugstr_w(value), dwModifier);
- TRACE("--> %s: %s - 0x%08lx\n", debugstr_w(field), debugstr_w(value), dwModifier);
+ TRACE("--> %s: %s - 0x%08x\n", debugstr_w(field), debugstr_w(value), dwModifier);
EnterCriticalSection( &request->headers_section );
- EnterCriticalSection( &request->headers_section );
+ EnterCriticalSection( &request->headers_section );
- /* REPLACE wins out over ADD */
- if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
@ -38,35 +42,40 @@ index ec984441399..98f63a8c0a4 100644
- index = -1;
- else
- index = HTTP_GetCustomHeaderIndex(request, field, 0, request_only);
-
+ index = HTTP_GetCustomHeaderIndex(request, field, 0, request_only);
if (index >= 0)
{
+ if (index >= 0)
+ {
+ lphttpHdr = &request->custHeaders[index];
- if (index >= 0)
- {
- if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
- {
+ /* replace existing header if FLAG_REPLACE is given */
+ if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
{
- LeaveCriticalSection( &request->headers_section );
- return ERROR_HTTP_INVALID_HEADER;
- }
lphttpHdr = &request->custHeaders[index];
- lphttpHdr = &request->custHeaders[index];
- }
- else if (value)
- {
- HTTPHEADERW hdr;
+ HTTP_DeleteCustomHeader( request, index );
- hdr.lpszField = (LPWSTR)field;
- hdr.lpszValue = (LPWSTR)value;
- hdr.wFlags = hdr.wCount = 0;
+ /* replace existing header if FLAG_REPLACE is given */
+ if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
+ {
+ HTTP_DeleteCustomHeader( request, index );
- if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
- hdr.wFlags |= HDR_ISREQUEST;
+ if (value && value[0])
+ {
+ HTTPHEADERW hdr;
- if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
- hdr.wFlags |= HDR_ISREQUEST;
+ hdr.lpszField = (LPWSTR)field;
+ hdr.lpszValue = (LPWSTR)value;
+ hdr.wFlags = hdr.wCount = 0;
- res = HTTP_InsertCustomHeader(request, &hdr);
- LeaveCriticalSection( &request->headers_section );
- return res;
@ -77,69 +86,46 @@ index ec984441399..98f63a8c0a4 100644
- LeaveCriticalSection( &request->headers_section );
- return ERROR_SUCCESS;
- }
+ hdr.lpszField = (LPWSTR)field;
+ hdr.lpszValue = (LPWSTR)value;
+ hdr.wFlags = hdr.wCount = 0;
+ if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
+ hdr.wFlags |= HDR_ISREQUEST;
- if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
- lphttpHdr->wFlags |= HDR_ISREQUEST;
- else
- lphttpHdr->wFlags &= ~HDR_ISREQUEST;
+ if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
+ hdr.wFlags |= HDR_ISREQUEST;
+ res = HTTP_InsertCustomHeader( request, &hdr );
+ }
- if (dwModifier & HTTP_ADDHDR_FLAG_REPLACE)
- {
- HTTP_DeleteCustomHeader( request, index );
+ res = HTTP_InsertCustomHeader( request, &hdr );
+ }
+
+ goto out;
+ }
- if (value && value[0])
+ /* do not add new header if FLAG_ADD_IF_NEW is set */
+ if (dwModifier & HTTP_ADDHDR_FLAG_ADD_IF_NEW)
{
- HTTPHEADERW hdr;
+ {
+ res = ERROR_HTTP_INVALID_HEADER; /* FIXME */
+ goto out;
+ }
- hdr.lpszField = (LPWSTR)field;
- hdr.lpszValue = (LPWSTR)value;
- hdr.wFlags = hdr.wCount = 0;
+
+ /* handle appending to existing header */
+ if (dwModifier & COALESCEFLAGS)
+ {
{
- HTTPHEADERW hdr;
+ LPWSTR lpsztmp;
+ WCHAR ch = 0;
+ INT len = 0;
+ INT origlen = lstrlenW(lphttpHdr->lpszValue);
+ INT valuelen = lstrlenW(value);
+
+ /* FIXME: Should it really clear HDR_ISREQUEST? */
if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
- hdr.wFlags |= HDR_ISREQUEST;
-
- res = HTTP_InsertCustomHeader(request, &hdr);
- LeaveCriticalSection( &request->headers_section );
- return res;
- }
+ if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
+ lphttpHdr->wFlags |= HDR_ISREQUEST;
+ else
+ lphttpHdr->wFlags &= ~HDR_ISREQUEST;
- LeaveCriticalSection( &request->headers_section );
- return ERROR_SUCCESS;
- }
- else if (dwModifier & COALESCEFLAGS)
- {
- LPWSTR lpsztmp;
- WCHAR ch = 0;
- INT len = 0;
- INT origlen = lstrlenW(lphttpHdr->lpszValue);
- INT valuelen = lstrlenW(value);
+
+ if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA)
+ {
+ ch = ',';
@ -151,19 +137,13 @@ index ec984441399..98f63a8c0a4 100644
+ lphttpHdr->wFlags |= HDR_COMMADELIMITED;
+ }
- if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA)
- {
- ch = ',';
- lphttpHdr->wFlags |= HDR_COMMADELIMITED;
- }
- else if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
- {
- ch = ';';
- lphttpHdr->wFlags |= HDR_COMMADELIMITED;
- }
- hdr.lpszField = (LPWSTR)field;
- hdr.lpszValue = (LPWSTR)value;
- hdr.wFlags = hdr.wCount = 0;
+ len = origlen + valuelen + ((ch > 0) ? 2 : 0);
- len = origlen + valuelen + ((ch > 0) ? 2 : 0);
- if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
- hdr.wFlags |= HDR_ISREQUEST;
+ lpsztmp = heap_realloc(lphttpHdr->lpszValue, (len+1)*sizeof(WCHAR));
+ if (lpsztmp)
+ {
@ -177,24 +157,73 @@ index ec984441399..98f63a8c0a4 100644
+ origlen++;
+ }
- res = HTTP_InsertCustomHeader(request, &hdr);
- LeaveCriticalSection( &request->headers_section );
- return res;
- }
+ memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
+ lphttpHdr->lpszValue[len] = '\0';
+ }
+ else
+ {
+ WARN("heap_realloc (%d bytes) failed\n",len+1);
+ res = ERROR_OUTOFMEMORY;
+ }
- LeaveCriticalSection( &request->headers_section );
- return ERROR_SUCCESS;
- }
- else if (dwModifier & COALESCEFLAGS)
+ goto out;
+ }
+ }
+
+ /* FIXME: What about other combinations? */
+ if ((dwModifier & ~HTTP_ADDHDR_FLAG_REQ) == HTTP_ADDHDR_FLAG_REPLACE)
{
- LPWSTR lpsztmp;
- WCHAR ch = 0;
- INT len = 0;
- INT origlen = lstrlenW(lphttpHdr->lpszValue);
- INT valuelen = lstrlenW(value);
+ res = ERROR_HTTP_HEADER_NOT_FOUND;
+ goto out;
+ }
- if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_COMMA)
- {
- ch = ',';
- lphttpHdr->wFlags |= HDR_COMMADELIMITED;
- }
- else if (dwModifier & HTTP_ADDHDR_FLAG_COALESCE_WITH_SEMICOLON)
- {
- ch = ';';
- lphttpHdr->wFlags |= HDR_COMMADELIMITED;
- }
+ /* FIXME: What if value == ""? */
+ if (value)
+ {
+ HTTPHEADERW hdr;
- len = origlen + valuelen + ((ch > 0) ? 2 : 0);
+ hdr.lpszField = (LPWSTR)field;
+ hdr.lpszValue = (LPWSTR)value;
+ hdr.wFlags = hdr.wCount = 0;
- lpsztmp = heap_realloc(lphttpHdr->lpszValue, (len+1)*sizeof(WCHAR));
- if (lpsztmp)
- {
- lphttpHdr->lpszValue = lpsztmp;
- /* FIXME: Increment lphttpHdr->wCount. Perhaps lpszValue should be an array */
- if (ch > 0)
+ memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
+ lphttpHdr->lpszValue[len] = '\0';
+ }
+ else
{
- {
- lphttpHdr->lpszValue[origlen] = ch;
- origlen++;
- lphttpHdr->lpszValue[origlen] = ' ';
- origlen++;
+ WARN("heap_realloc (%d bytes) failed\n",len+1);
+ res = ERROR_OUTOFMEMORY;
}
- }
+ if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
+ hdr.wFlags |= HDR_ISREQUEST;
- memcpy(&lphttpHdr->lpszValue[origlen], value, valuelen*sizeof(WCHAR));
- lphttpHdr->lpszValue[len] = '\0';
@ -204,38 +233,22 @@ index ec984441399..98f63a8c0a4 100644
- {
- WARN("heap_realloc (%d bytes) failed\n",len+1);
- res = ERROR_OUTOFMEMORY;
+ goto out;
}
}
+
+ /* FIXME: What about other combinations? */
+ if ((dwModifier & ~HTTP_ADDHDR_FLAG_REQ) == HTTP_ADDHDR_FLAG_REPLACE)
+ {
+ res = ERROR_HTTP_HEADER_NOT_FOUND;
+ goto out;
+ }
+
+ /* FIXME: What if value == ""? */
+ if (value)
+ {
+ HTTPHEADERW hdr;
+
+ hdr.lpszField = (LPWSTR)field;
+ hdr.lpszValue = (LPWSTR)value;
+ hdr.wFlags = hdr.wCount = 0;
+
+ if (dwModifier & HTTP_ADDHDR_FLAG_REQ)
+ hdr.wFlags |= HDR_ISREQUEST;
+
- }
+ res = HTTP_InsertCustomHeader( request, &hdr );
+ goto out;
+ }
}
- TRACE("<-- %ld\n", res);
- LeaveCriticalSection( &request->headers_section );
- return res;
+
+ /* FIXME: What if value == NULL? */
+out:
TRACE("<-- %d\n", res);
LeaveCriticalSection( &request->headers_section );
return res;
+ TRACE("<-- %ld\n", res);
+ LeaveCriticalSection( &request->headers_section );
+ return res;
}
/***********************************************************************
--
2.17.1
2.34.1

View File

@ -1,18 +1,18 @@
From 851ba662c66ef27b8fa87417829d3e134d349542 Mon Sep 17 00:00:00 2001
From f32d9d5f3b9b4b3e54037211f5d561681ed589fa Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Michael=20M=C3=BCller?= <michael@fds-team.de>
Date: Fri, 4 Mar 2016 16:15:50 +0100
Subject: winmm: Do not crash in Win 9X mode when an invalid device ptr is
passed to MCI_OPEN.
Subject: [PATCH] winmm: Do not crash in Win 9X mode when an invalid device ptr
is passed to MCI_OPEN.
---
dlls/winmm/mci.c | 40 +++++++++++++++++++---------------------
1 file changed, 19 insertions(+), 21 deletions(-)
dlls/winmm/mci.c | 42 ++++++++++++++++++++----------------------
1 file changed, 20 insertions(+), 22 deletions(-)
diff --git a/dlls/winmm/mci.c b/dlls/winmm/mci.c
index b3c1882..3e58063 100644
index 2aa74fd4127..5b8463286e5 100644
--- a/dlls/winmm/mci.c
+++ b/dlls/winmm/mci.c
@@ -218,7 +218,7 @@ static LPWSTR MCI_strdupAtoW( LPCSTR str )
@@ -209,7 +209,7 @@ static LPWSTR MCI_strdupAtoW( LPCSTR str )
return ret;
}
@ -21,7 +21,7 @@ index b3c1882..3e58063 100644
{
if (msg < DRV_RESERVED) return 0;
@@ -261,8 +261,12 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -252,8 +252,12 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
MCI_ANIM_OPEN_PARMSW *mci_openW;
DWORD_PTR *ptr;
@ -35,7 +35,7 @@ index b3c1882..3e58063 100644
*ptr++ = *dwParam2; /* save the previous pointer */
*dwParam2 = (DWORD_PTR)ptr;
@@ -292,7 +296,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -283,7 +287,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
if (HIWORD(dwParam1))
memcpy(&mci_openW->dwStyle, &mci_openA->dwStyle, sizeof(MCI_ANIM_OPEN_PARMSW) - sizeof(MCI_OPEN_PARMSW));
}
@ -44,7 +44,7 @@ index b3c1882..3e58063 100644
case MCI_WINDOW:
if (dwParam1 & MCI_ANIM_WINDOW_TEXT)
@@ -301,7 +305,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -292,7 +296,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
MCI_ANIM_WINDOW_PARMSW *mci_windowW;
mci_windowW = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_windowW));
@ -53,7 +53,7 @@ index b3c1882..3e58063 100644
*dwParam2 = (DWORD_PTR)mci_windowW;
@@ -313,8 +317,6 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -304,8 +308,6 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
mci_windowW->hWnd = mci_windowA->hWnd;
if (dwParam1 & MCI_ANIM_WINDOW_STATE)
mci_windowW->nCmdShow = mci_windowA->nCmdShow;
@ -62,7 +62,7 @@ index b3c1882..3e58063 100644
}
return 0;
@@ -326,7 +328,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -317,7 +319,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
DWORD_PTR *ptr;
ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_sysinfoW) + sizeof(DWORD_PTR));
@ -71,7 +71,7 @@ index b3c1882..3e58063 100644
*ptr++ = *dwParam2; /* save the previous pointer */
*dwParam2 = (DWORD_PTR)ptr;
@@ -340,7 +342,6 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -331,7 +333,6 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
mci_sysinfoW->lpstrReturn = HeapAlloc(GetProcessHeap(), 0, mci_sysinfoW->dwRetSize * sizeof(WCHAR));
mci_sysinfoW->dwNumber = mci_sysinfoA->dwNumber;
mci_sysinfoW->wDeviceType = mci_sysinfoA->wDeviceType;
@ -79,7 +79,7 @@ index b3c1882..3e58063 100644
}
return 0;
case MCI_INFO:
@@ -350,7 +351,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -341,7 +342,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
DWORD_PTR *ptr;
ptr = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_infoW) + sizeof(DWORD_PTR));
@ -88,7 +88,7 @@ index b3c1882..3e58063 100644
*ptr++ = *dwParam2; /* save the previous pointer */
*dwParam2 = (DWORD_PTR)ptr;
@@ -364,8 +365,8 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -355,8 +356,8 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
mci_infoW->lpstrReturn = HeapAlloc(GetProcessHeap(), 0, mci_infoW->dwRetSize * sizeof(WCHAR));
if (dwParam1 & MCI_DGV_INFO_ITEM)
mci_infoW->dwItem = mci_infoA->dwItem;
@ -98,7 +98,7 @@ index b3c1882..3e58063 100644
case MCI_SAVE:
case MCI_LOAD:
case MCI_CAPTURE:
@@ -375,7 +376,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -366,7 +367,7 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
MCI_OVLY_LOAD_PARMSW *mci_loadW;
mci_loadW = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_loadW));
@ -107,7 +107,7 @@ index b3c1882..3e58063 100644
*dwParam2 = (DWORD_PTR)mci_loadW;
if (dwParam1 & MCI_NOTIFY)
@@ -386,8 +387,8 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -377,8 +378,8 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
(MCI_CAPTURE == msg && dwParam1 & MCI_DGV_CAPTURE_AT) ||
(MCI_RESTORE == msg && dwParam1 & MCI_DGV_RESTORE_AT))
mci_loadW->rc = mci_loadA->rc;
@ -117,7 +117,7 @@ index b3c1882..3e58063 100644
case MCI_SOUND:
case MCI_ESCAPE:
{ /* All these commands have the same layout: callback + string */
@@ -395,14 +396,14 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
@@ -386,14 +387,14 @@ static int MCI_MapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR *dwParam2)
MCI_VD_ESCAPE_PARMSW *mci_vd_escapeW;
mci_vd_escapeW = HeapAlloc(GetProcessHeap(), 0, sizeof(*mci_vd_escapeW));
@ -134,7 +134,7 @@ index b3c1882..3e58063 100644
case MCI_SETAUDIO:
case MCI_SETVIDEO:
if (!(dwParam1 & (MCI_DGV_SETVIDEO_QUALITY | MCI_DGV_SETVIDEO_ALG
@@ -515,7 +516,6 @@ static void MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2,
@@ -506,7 +507,6 @@ static void MCI_UnmapMsgAtoW(UINT msg, DWORD_PTR dwParam1, DWORD_PTR dwParam2,
break;
default:
@ -142,13 +142,13 @@ index b3c1882..3e58063 100644
break;
}
}
@@ -2304,20 +2304,18 @@ DWORD WINAPI mciSendCommandW(MCIDEVICEID wDevID, UINT wMsg, DWORD_PTR dwParam1,
@@ -2289,20 +2289,18 @@ DWORD WINAPI mciSendCommandW(MCIDEVICEID wDevID, UINT wMsg, DWORD_PTR dwParam1,
DWORD WINAPI mciSendCommandA(MCIDEVICEID wDevID, UINT wMsg, DWORD_PTR dwParam1, DWORD_PTR dwParam2)
{
DWORD ret;
- int mapped;
TRACE("(%08x, %s, %08lx, %08lx)\n",
TRACE("(%08x, %s, %08Ix, %08Ix)\n",
wDevID, MCI_MessageToString(wMsg), dwParam1, dwParam2);
- mapped = MCI_MapMsgAtoW(wMsg, dwParam1, &dwParam2);
@ -160,13 +160,14 @@ index b3c1882..3e58063 100644
- return MCIERR_OUT_OF_MEMORY;
+ return ret;
}
ret = mciSendCommandW(wDevID, wMsg, dwParam1, dwParam2);
- ret = mciSendCommandW(wDevID, wMsg, dwParam1, dwParam2);
- if (mapped)
- MCI_UnmapMsgAtoW(wMsg, dwParam1, dwParam2, ret);
+ ret = mciSendCommandW(wDevID, wMsg, dwParam1, dwParam2);
+ MCI_UnmapMsgAtoW(wMsg, dwParam1, dwParam2, ret);
return ret;
}
--
2.7.1
2.34.1

View File

@ -1,4 +1,4 @@
From 563f0ccc4f47914e1e2952cc4bc5673cbb97a5ae Mon Sep 17 00:00:00 2001
From 7f8f6898788adbb31318aaead591b129138288c2 Mon Sep 17 00:00:00 2001
From: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
Date: Wed, 18 Apr 2018 03:55:16 +0000
Subject: [PATCH] wintrust: Add parameter check in WTHelperGetProvCertFromChain
@ -10,10 +10,10 @@ Signed-off-by: Alistair Leslie-Hughes <leslie_alistair@hotmail.com>
2 files changed, 10 insertions(+), 1 deletion(-)
diff --git a/dlls/wintrust/tests/softpub.c b/dlls/wintrust/tests/softpub.c
index 1f87234..8b02e77 100644
index 25d458faad7..998cce85380 100644
--- a/dlls/wintrust/tests/softpub.c
+++ b/dlls/wintrust/tests/softpub.c
@@ -1300,6 +1300,14 @@ static void test_get_known_usages(void)
@@ -1312,6 +1312,14 @@ static void test_get_known_usages(void)
"expected ERROR_INVALID_PARAMETER, got %d\n", GetLastError());
}
@ -28,19 +28,19 @@ index 1f87234..8b02e77 100644
START_TEST(softpub)
{
InitFunctionPtrs();
@@ -1308,4 +1316,5 @@ START_TEST(softpub)
@@ -1320,4 +1328,5 @@ START_TEST(softpub)
test_wintrust();
test_wintrust_digest();
test_get_known_usages();
+ test_WTHelperGetProvCertFromChain();
}
diff --git a/dlls/wintrust/wintrust_main.c b/dlls/wintrust/wintrust_main.c
index 58e3ac3..bb52282 100644
index 33695008b24..60c633e5abf 100644
--- a/dlls/wintrust/wintrust_main.c
+++ b/dlls/wintrust/wintrust_main.c
@@ -787,7 +787,7 @@ CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
@@ -782,7 +782,7 @@ CRYPT_PROVIDER_CERT * WINAPI WTHelperGetProvCertFromChain(
TRACE("(%p %d)\n", pSgnr, idxCert);
TRACE("(%p %ld)\n", pSgnr, idxCert);
- if (idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
+ if (!pSgnr || idxCert >= pSgnr->csCertChain || !pSgnr->pasCertChain)
@ -48,5 +48,5 @@ index 58e3ac3..bb52282 100644
cert = &pSgnr->pasCertChain[idxCert];
TRACE("returning %p\n", cert);
--
1.9.1
2.34.1

View File

@ -1 +1 @@
53cb28e6d9daa7cbcc190cd02aeaba37c297adc4
4853f65c844de8277b8b0420df1a2cdb1c5b17c8