Wine-Devel
Threads by month
- ----- 2026 -----
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- 5 participants
- 84534 discussions
[PATCH v2 1/7] quartz/tests: Add some tests for IPin::EndOfStream() on the DirectSound renderer.
by Zebediah Figura Nov. 21, 2020
by Zebediah Figura Nov. 21, 2020
Nov. 21, 2020
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
v2: give w10pro64 more time
dlls/quartz/tests/dsoundrender.c | 142 +++++++++++++++++++++++++++++++
1 file changed, 142 insertions(+)
diff --git a/dlls/quartz/tests/dsoundrender.c b/dlls/quartz/tests/dsoundrender.c
index 558e6989c98..c33c074d93d 100644
--- a/dlls/quartz/tests/dsoundrender.c
+++ b/dlls/quartz/tests/dsoundrender.c
@@ -877,6 +877,147 @@ static void test_flushing(IPin *pin, IMemInputPin *input, IMediaControl *control
ok(hr == S_OK, "Got hr %#x.\n", hr);
}
+static unsigned int check_ec_complete(IMediaEvent *eventsrc, DWORD timeout)
+{
+ LONG_PTR param1, param2;
+ unsigned int ret = 0;
+ HRESULT hr;
+ LONG code;
+
+ while ((hr = IMediaEvent_GetEvent(eventsrc, &code, ¶m1, ¶m2, timeout)) == S_OK)
+ {
+ if (code == EC_COMPLETE)
+ {
+ ok(param1 == S_OK, "Got param1 %#lx.\n", param1);
+ ok(!param2, "Got param2 %#lx.\n", param2);
+ ret++;
+ }
+ IMediaEvent_FreeEventParams(eventsrc, code, param1, param2);
+ timeout = 0;
+ }
+ ok(hr == E_ABORT, "Got hr %#x.\n", hr);
+
+ return ret;
+}
+
+static void test_eos(IPin *pin, IMemInputPin *input, IMediaControl *control)
+{
+ IMediaEvent *eventsrc;
+ OAFilterState state;
+ HRESULT hr;
+ BOOL ret;
+
+ IMediaControl_QueryInterface(control, &IID_IMediaEvent, (void **)&eventsrc);
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ hr = IPin_EndOfStream(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_GetState(control, 1000, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ hr = send_frame(input);
+ todo_wine ok(hr == VFW_E_SAMPLE_REJECTED_EOS, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ todo_wine ok(ret == 1, "Expected EC_COMPLETE.\n");
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ /* We do not receive an EC_COMPLETE notification until the last sample is
+ * done rendering. */
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = send_frame(input);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IMediaControl_GetState(control, 1000, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ hr = IPin_EndOfStream(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+ ret = check_ec_complete(eventsrc, 2000);
+ todo_wine ok(ret == 1, "Expected EC_COMPLETE.\n");
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ /* Test sending EOS while flushing. */
+
+ hr = IMediaControl_Run(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = send_frame(input);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IPin_BeginFlush(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IPin_EndOfStream(pin);
+ todo_wine ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = IPin_EndFlush(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ /* Test sending EOS and then flushing or stopping. */
+
+ hr = IMediaControl_Pause(control);
+ ok(hr == S_FALSE, "Got hr %#x.\n", hr);
+ hr = send_frame(input);
+ todo_wine ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IMediaControl_GetState(control, 1000, &state);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IMediaControl_Run(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ hr = IPin_EndOfStream(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ hr = IPin_BeginFlush(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IPin_EndFlush(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+
+ hr = send_frame(input);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ hr = IPin_EndOfStream(pin);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ hr = IMediaControl_Stop(control);
+ ok(hr == S_OK, "Got hr %#x.\n", hr);
+ ret = check_ec_complete(eventsrc, 0);
+ ok(!ret, "Got unexpected EC_COMPLETE.\n");
+
+ IMediaEvent_Release(eventsrc);
+}
+
static void test_connect_pin(void)
{
ALLOCATOR_PROPERTIES req_props = {1, 4 * 44100, 1, 0}, ret_props;
@@ -971,6 +1112,7 @@ static void test_connect_pin(void)
test_filter_state(input, control);
test_flushing(pin, input, control);
+ test_eos(pin, input, control);
hr = IFilterGraph2_Disconnect(graph, pin);
ok(hr == S_OK, "Got hr %#x.\n", hr);
--
2.29.2
1
6
Signed-off-by: Jeff Smith <whydoubt(a)gmail.com>
---
dlls/gdiplus/font.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/gdiplus/font.c b/dlls/gdiplus/font.c
index b0504b5d894..4301fa3aaa3 100644
--- a/dlls/gdiplus/font.c
+++ b/dlls/gdiplus/font.c
@@ -1037,7 +1037,7 @@ GpStatus WINGDIPAPI GdipGetGenericFontFamilySansSerif(GpFontFamily **nativeFamil
}
/*****************************************************************************
- * GdipGetGenericFontFamilySansSerif [GDIPLUS.@]
+ * GdipNewPrivateFontCollection [GDIPLUS.@]
*/
GpStatus WINGDIPAPI GdipNewPrivateFontCollection(GpFontCollection** fontCollection)
{
--
2.23.0
2
3
Binary packages for various distributions will be available from:
https://www.winehq.org/download
Summary since last release
* Rebased to current wine 5.22 (685 patches are applied to wine vanilla)
Upstreamed (Either directly from staging or fixed with a similar patch).
* winegstreamer: Implement IMFMediaSource::GetCharacteristics.
* winegstreamer: Calculate the MF_PD_DURATION of the media source's PD.
* winspool: Add sRGB color profile
* dxdiagn: Enumerate DirectSound devices and add some basic properties.
* dxdiagn: Calling GetChildContainer with an empty string on a leaf
container returns the object itself
Added:
* None
Updated:
* mfplat-streaming-support
* eventfd_synchronization
Where can you help
* Run Steam/Battle.net/GOG/UPlay/Epic
* Test your favorite game.
* Test your favorite applications.
* Improve staging patches and get them accepted upstream.
As always, if you find a bug, please report it via
https://bugs.winehq.org
Best Regards
Alistair.
1
0
[PATCH] ntdll: Use a dynamically allocated buffer in find_forwarded_export() if necessary.
by Zebediah Figura Nov. 20, 2020
by Zebediah Figura Nov. 20, 2020
Nov. 20, 2020
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=50105
Signed-off-by: Zebediah Figura <z.figura12(a)gmail.com>
---
dlls/ntdll/loader.c | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index 368448c9f8d..ff5a175027c 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -608,19 +608,20 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS
const IMAGE_EXPORT_DIRECTORY *exports;
DWORD exp_size;
WINE_MODREF *wm;
- WCHAR mod_name[32];
+ WCHAR buffer[32], *mod_name = buffer;
const char *end = strrchr(forward, '.');
FARPROC proc = NULL;
if (!end) return NULL;
- if ((end - forward) * sizeof(WCHAR) >= sizeof(mod_name)) return NULL;
+ if ((end - forward) * sizeof(WCHAR) > sizeof(buffer) - sizeof(dllW))
+ {
+ if (!(mod_name = RtlAllocateHeap( GetProcessHeap(), 0, (end - forward + sizeof(dllW)) * sizeof(WCHAR) )))
+ return NULL;
+ }
ascii_to_unicode( mod_name, forward, end - forward );
mod_name[end - forward] = 0;
if (!wcschr( mod_name, '.' ))
- {
- if ((end - forward) * sizeof(WCHAR) >= sizeof(mod_name) - sizeof(dllW)) return NULL;
memcpy( mod_name + (end - forward), dllW, sizeof(dllW) );
- }
if (!(wm = find_basename_module( mod_name )))
{
@@ -642,6 +643,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS
if (!wm)
{
+ if (mod_name != buffer) RtlFreeHeap( GetProcessHeap(), 0, mod_name );
ERR( "module not found for forward '%s' used by %s\n",
forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer) );
return NULL;
@@ -664,6 +666,7 @@ static FARPROC find_forwarded_export( HMODULE module, const char *forward, LPCWS
forward, debugstr_w(get_modref(module)->ldr.FullDllName.Buffer),
debugstr_w(get_modref(module)->ldr.BaseDllName.Buffer) );
}
+ if (mod_name != buffer) RtlFreeHeap( GetProcessHeap(), 0, mod_name );
return proc;
}
--
2.29.2
2
1
Nov. 20, 2020
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/libpng.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/dlls/windowscodecs/libpng.c b/dlls/windowscodecs/libpng.c
index ee02d493f57..a5068c20349 100644
--- a/dlls/windowscodecs/libpng.c
+++ b/dlls/windowscodecs/libpng.c
@@ -997,6 +997,7 @@ HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **res
This->data = NULL;
*result = &This->encoder;
+ info->flags = 0;
info->container_format = GUID_ContainerFormatPng;
info->clsid = CLSID_WICPngEncoder;
info->encoder_options[0] = ENCODER_OPTION_INTERLACE;
--
2.17.1
1
0
Nov. 20, 2020
Signed-off-by: Esme Povirk <esme(a)codeweavers.com>
---
dlls/windowscodecs/Makefile.in | 1 -
dlls/windowscodecs/encoder.c | 6 +-
dlls/windowscodecs/libtiff.c | 260 +++++-
dlls/windowscodecs/main.c | 28 +
dlls/windowscodecs/tiffformat.c | 1001 ------------------------
dlls/windowscodecs/unix_lib.c | 3 +
dlls/windowscodecs/wincodecs_private.h | 3 +
7 files changed, 297 insertions(+), 1005 deletions(-)
delete mode 100644 dlls/windowscodecs/tiffformat.c
diff --git a/dlls/windowscodecs/Makefile.in b/dlls/windowscodecs/Makefile.in
index e175359ab9d..d7f9336916b 100644
--- a/dlls/windowscodecs/Makefile.in
+++ b/dlls/windowscodecs/Makefile.in
@@ -37,7 +37,6 @@ C_SRCS = \
scaler.c \
stream.c \
tgaformat.c \
- tiffformat.c \
ungif.c \
unix_iface.c \
unix_lib.c \
diff --git a/dlls/windowscodecs/encoder.c b/dlls/windowscodecs/encoder.c
index 0ddc54cc57e..bb673b13076 100644
--- a/dlls/windowscodecs/encoder.c
+++ b/dlls/windowscodecs/encoder.c
@@ -36,10 +36,14 @@ WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
static const WCHAR wszPngInterlaceOption[] = {'I','n','t','e','r','l','a','c','e','O','p','t','i','o','n',0};
static const WCHAR wszPngFilterOption[] = {'F','i','l','t','e','r','O','p','t','i','o','n',0};
+static const WCHAR wszTiffCompressionMethod[] = {'T','i','f','f','C','o','m','p','r','e','s','s','i','o','n','M','e','t','h','o','d',0};
+static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
static const PROPBAG2 encoder_option_properties[ENCODER_OPTION_END] = {
{ PROPBAG2_TYPE_DATA, VT_BOOL, 0, 0, (LPOLESTR)wszPngInterlaceOption },
- { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszPngFilterOption }
+ { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszPngFilterOption },
+ { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszTiffCompressionMethod },
+ { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszCompressionQuality }
};
typedef struct CommonEncoder {
diff --git a/dlls/windowscodecs/libtiff.c b/dlls/windowscodecs/libtiff.c
index 7f174bbd5dd..6f5cfc53c62 100644
--- a/dlls/windowscodecs/libtiff.c
+++ b/dlls/windowscodecs/libtiff.c
@@ -143,8 +143,13 @@ static tsize_t tiff_stream_read(thandle_t client_data, tdata_t data, tsize_t siz
static tsize_t tiff_stream_write(thandle_t client_data, tdata_t data, tsize_t size)
{
- FIXME("stub\n");
- return 0;
+ IStream *stream = (IStream*)client_data;
+ ULONG bytes_written;
+ HRESULT hr;
+
+ hr = stream_write(stream, data, size, &bytes_written);
+ if (FAILED(hr)) bytes_written = 0;
+ return bytes_written;
}
static toff_t tiff_stream_seek(thandle_t client_data, toff_t offset, int whence)
@@ -1176,6 +1181,251 @@ HRESULT CDECL tiff_decoder_create(struct decoder_info *info, struct decoder **re
return S_OK;
}
+struct tiff_encode_format {
+ const WICPixelFormatGUID *guid;
+ int photometric;
+ int bps;
+ int samples;
+ int bpp;
+ int extra_sample;
+ int extra_sample_type;
+ int reverse_bgr;
+ int indexed;
+};
+
+static const struct tiff_encode_format formats[] = {
+ {&GUID_WICPixelFormat24bppBGR, 2, 8, 3, 24, 0, 0, 1},
+ {&GUID_WICPixelFormat24bppRGB, 2, 8, 3, 24, 0, 0, 0},
+ {&GUID_WICPixelFormatBlackWhite, 1, 1, 1, 1, 0, 0, 0},
+ {&GUID_WICPixelFormat4bppGray, 1, 4, 1, 4, 0, 0, 0},
+ {&GUID_WICPixelFormat8bppGray, 1, 8, 1, 8, 0, 0, 0},
+ {&GUID_WICPixelFormat32bppBGRA, 2, 8, 4, 32, 1, 2, 1},
+ {&GUID_WICPixelFormat32bppPBGRA, 2, 8, 4, 32, 1, 1, 1},
+ {&GUID_WICPixelFormat48bppRGB, 2, 16, 3, 48, 0, 0, 0},
+ {&GUID_WICPixelFormat64bppRGBA, 2, 16, 4, 64, 1, 2, 0},
+ {&GUID_WICPixelFormat64bppPRGBA, 2, 16, 4, 64, 1, 1, 0},
+ {&GUID_WICPixelFormat1bppIndexed, 3, 1, 1, 1, 0, 0, 0, 1},
+ {&GUID_WICPixelFormat4bppIndexed, 3, 4, 1, 4, 0, 0, 0, 1},
+ {&GUID_WICPixelFormat8bppIndexed, 3, 8, 1, 8, 0, 0, 0, 1},
+ {0}
+};
+
+typedef struct tiff_encoder {
+ struct encoder encoder;
+ TIFF *tiff;
+ const struct tiff_encode_format *format;
+ struct encoder_frame encoder_frame;
+ DWORD num_frames;
+ DWORD lines_written;
+} tiff_encoder;
+
+static inline struct tiff_encoder *impl_from_encoder(struct encoder* iface)
+{
+ return CONTAINING_RECORD(iface, struct tiff_encoder, encoder);
+}
+
+static HRESULT CDECL tiff_encoder_initialize(struct encoder* iface, IStream *stream)
+{
+ struct tiff_encoder* This = impl_from_encoder(iface);
+ TIFF *tiff;
+
+ tiff = tiff_open_stream(stream, "w");
+
+ if (!tiff)
+ return E_FAIL;
+
+ This->tiff = tiff;
+
+ return S_OK;
+}
+
+static HRESULT CDECL tiff_encoder_get_supported_format(struct encoder *iface,
+ GUID *pixel_format, DWORD *bpp, BOOL *indexed)
+{
+ int i;
+
+ if (IsEqualGUID(pixel_format, &GUID_WICPixelFormat2bppIndexed))
+ *pixel_format = GUID_WICPixelFormat4bppIndexed;
+
+ for (i=0; formats[i].guid; i++)
+ {
+ if (IsEqualGUID(formats[i].guid, pixel_format))
+ break;
+ }
+
+ if (!formats[i].guid) i = 0;
+
+ *pixel_format = *formats[i].guid;
+ *bpp = formats[i].bpp;
+ *indexed = formats[i].indexed;
+
+ return S_OK;
+}
+
+static HRESULT CDECL tiff_encoder_create_frame(struct encoder* iface, const struct encoder_frame *frame)
+{
+ struct tiff_encoder* This = impl_from_encoder(iface);
+ int i;
+
+ if (This->num_frames != 0)
+ pTIFFWriteDirectory(This->tiff);
+
+ This->num_frames++;
+ This->lines_written = 0;
+ This->encoder_frame = *frame;
+
+ for (i=0; formats[i].guid; i++)
+ {
+ if (IsEqualGUID(formats[i].guid, &frame->pixel_format))
+ break;
+ }
+
+ This->format = &formats[i];
+
+ pTIFFSetField(This->tiff, TIFFTAG_PHOTOMETRIC, (uint16)This->format->photometric);
+ pTIFFSetField(This->tiff, TIFFTAG_PLANARCONFIG, (uint16)1);
+ pTIFFSetField(This->tiff, TIFFTAG_BITSPERSAMPLE, (uint16)This->format->bps);
+ pTIFFSetField(This->tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16)This->format->samples);
+
+ if (This->format->extra_sample)
+ {
+ uint16 extra_samples;
+ extra_samples = This->format->extra_sample_type;
+
+ pTIFFSetField(This->tiff, TIFFTAG_EXTRASAMPLES, (uint16)1, &extra_samples);
+ }
+
+ pTIFFSetField(This->tiff, TIFFTAG_IMAGEWIDTH, (uint32)frame->width);
+ pTIFFSetField(This->tiff, TIFFTAG_IMAGELENGTH, (uint32)frame->height);
+
+ if (frame->dpix != 0.0 && frame->dpiy != 0.0)
+ {
+ pTIFFSetField(This->tiff, TIFFTAG_RESOLUTIONUNIT, (uint16)2); /* Inch */
+ pTIFFSetField(This->tiff, TIFFTAG_XRESOLUTION, (float)frame->dpix);
+ pTIFFSetField(This->tiff, TIFFTAG_YRESOLUTION, (float)frame->dpiy);
+ }
+
+ if (This->format->bpp <= 8 && frame->num_colors && This->format->indexed)
+ {
+ uint16 red[256], green[256], blue[256];
+ UINT i;
+
+ for (i = 0; i < frame->num_colors; i++)
+ {
+ red[i] = (frame->palette[i] >> 8) & 0xff00;
+ green[i] = frame->palette[i] & 0xff00;
+ blue[i] = (frame->palette[i] << 8) & 0xff00;
+ }
+
+ pTIFFSetField(This->tiff, TIFFTAG_COLORMAP, red, green, blue);
+ }
+
+ return S_OK;
+}
+
+static HRESULT CDECL tiff_encoder_write_lines(struct encoder* iface,
+ BYTE *data, DWORD line_count, DWORD stride)
+{
+ struct tiff_encoder* This = impl_from_encoder(iface);
+ BYTE *row_data, *swapped_data = NULL;
+ UINT i, j, line_size;
+
+ line_size = ((This->encoder_frame.width * This->format->bpp)+7)/8;
+
+ if (This->format->reverse_bgr)
+ {
+ swapped_data = malloc(line_size);
+ if (!swapped_data)
+ return E_OUTOFMEMORY;
+ }
+
+ for (i=0; i<line_count; i++)
+ {
+ row_data = data + i * stride;
+
+ if (This->format->reverse_bgr && This->format->bps == 8)
+ {
+ memcpy(swapped_data, row_data, line_size);
+ for (j=0; j<line_size; j += This->format->samples)
+ {
+ BYTE temp;
+ temp = swapped_data[j];
+ swapped_data[j] = swapped_data[j+2];
+ swapped_data[j+2] = temp;
+ }
+ row_data = swapped_data;
+ }
+
+ pTIFFWriteScanline(This->tiff, (tdata_t)row_data, i+This->lines_written, 0);
+ }
+
+ This->lines_written += line_count;
+
+ return S_OK;
+}
+
+static HRESULT CDECL tiff_encoder_commit_frame(struct encoder* iface)
+{
+ return S_OK;
+}
+
+static HRESULT CDECL tiff_encoder_commit_file(struct encoder* iface)
+{
+ struct tiff_encoder* This = impl_from_encoder(iface);
+
+ pTIFFClose(This->tiff);
+ This->tiff = NULL;
+
+ return S_OK;
+}
+
+static void CDECL tiff_encoder_destroy(struct encoder* iface)
+{
+ struct tiff_encoder *This = impl_from_encoder(iface);
+
+ if (This->tiff) pTIFFClose(This->tiff);
+ RtlFreeHeap(GetProcessHeap(), 0, This);
+}
+
+static const struct encoder_funcs tiff_encoder_vtable = {
+ tiff_encoder_initialize,
+ tiff_encoder_get_supported_format,
+ tiff_encoder_create_frame,
+ tiff_encoder_write_lines,
+ tiff_encoder_commit_frame,
+ tiff_encoder_commit_file,
+ tiff_encoder_destroy
+};
+
+HRESULT CDECL tiff_encoder_create(struct encoder_info *info, struct encoder **result)
+{
+ struct tiff_encoder *This;
+
+ if (!load_libtiff())
+ {
+ ERR("Failed writing TIFF because unable to load %s\n",SONAME_LIBTIFF);
+ return E_FAIL;
+ }
+
+ This = RtlAllocateHeap(GetProcessHeap(), 0, sizeof(*This));
+ if (!This) return E_OUTOFMEMORY;
+
+ This->encoder.vtable = &tiff_encoder_vtable;
+ This->tiff = NULL;
+ This->num_frames = 0;
+
+ info->flags = ENCODER_FLAGS_MULTI_FRAME;
+ info->container_format = GUID_ContainerFormatTiff;
+ info->clsid = CLSID_WICTiffEncoder;
+ info->encoder_options[0] = ENCODER_OPTION_COMPRESSION_METHOD;
+ info->encoder_options[1] = ENCODER_OPTION_COMPRESSION_QUALITY;
+ info->encoder_options[2] = ENCODER_OPTION_END;
+
+ *result = &This->encoder;
+
+ return S_OK;
+}
+
#else /* !SONAME_LIBTIFF */
HRESULT CDECL tiff_decoder_create(struct decoder_info *info, struct decoder **result)
@@ -1184,4 +1434,10 @@ HRESULT CDECL tiff_decoder_create(struct decoder_info *info, struct decoder **re
return E_FAIL;
}
+HRESULT CDECL tiff_encoder_create(struct encoder_info *info, struct encoder **result)
+{
+ ERR("Trying to save TIFF picture, but Wine was compiled without TIFF support.\n");
+ return E_FAIL;
+}
+
#endif
diff --git a/dlls/windowscodecs/main.c b/dlls/windowscodecs/main.c
index 3817d23eb4c..bc12eb2fda1 100644
--- a/dlls/windowscodecs/main.c
+++ b/dlls/windowscodecs/main.c
@@ -251,3 +251,31 @@ HRESULT get_pixelformat_bpp(const GUID *pixelformat, UINT *bpp)
return hr;
}
+
+HRESULT TiffDecoder_CreateInstance(REFIID iid, void** ppv)
+{
+ HRESULT hr;
+ struct decoder *decoder;
+ struct decoder_info decoder_info;
+
+ hr = get_unix_decoder(&CLSID_WICTiffDecoder, &decoder_info, &decoder);
+
+ if (SUCCEEDED(hr))
+ hr = CommonDecoder_CreateInstance(decoder, &decoder_info, iid, ppv);
+
+ return hr;
+}
+
+HRESULT TiffEncoder_CreateInstance(REFIID iid, void** ppv)
+{
+ HRESULT hr;
+ struct encoder *encoder;
+ struct encoder_info encoder_info;
+
+ hr = get_unix_encoder(&CLSID_WICTiffEncoder, &encoder_info, &encoder);
+
+ if (SUCCEEDED(hr))
+ hr = CommonEncoder_CreateInstance(encoder, &encoder_info, iid, ppv);
+
+ return hr;
+}
diff --git a/dlls/windowscodecs/tiffformat.c b/dlls/windowscodecs/tiffformat.c
deleted file mode 100644
index b2478380334..00000000000
--- a/dlls/windowscodecs/tiffformat.c
+++ /dev/null
@@ -1,1001 +0,0 @@
-/*
- * Copyright 2010 Vincent Povirk for CodeWeavers
- * Copyright 2016 Dmitry Timoshkov
- *
- * 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 "config.h"
-#include "wine/port.h"
-
-#include <stdarg.h>
-#ifdef HAVE_UNISTD_H
-#include <unistd.h>
-#endif
-#ifdef HAVE_TIFFIO_H
-#include <tiffio.h>
-#endif
-
-#define COBJMACROS
-
-#include "windef.h"
-#include "winbase.h"
-#include "objbase.h"
-
-#include "wincodecs_private.h"
-
-#include "wine/debug.h"
-
-WINE_DEFAULT_DEBUG_CHANNEL(wincodecs);
-
-#ifdef SONAME_LIBTIFF
-
-/* Workaround for broken libtiff 4.x headers on some 64-bit hosts which
- * define TIFF_UINT64_T/toff_t as 32-bit for 32-bit builds, while they
- * are supposed to be always 64-bit.
- * TIFF_UINT64_T doesn't exist in libtiff 3.x, it was introduced in 4.x.
- */
-#ifdef TIFF_UINT64_T
-# undef toff_t
-# define toff_t UINT64
-#endif
-
-static CRITICAL_SECTION init_tiff_cs;
-static CRITICAL_SECTION_DEBUG init_tiff_cs_debug =
-{
- 0, 0, &init_tiff_cs,
- { &init_tiff_cs_debug.ProcessLocksList,
- &init_tiff_cs_debug.ProcessLocksList },
- 0, 0, { (DWORD_PTR)(__FILE__ ": init_tiff_cs") }
-};
-static CRITICAL_SECTION init_tiff_cs = { &init_tiff_cs_debug, -1, 0, 0, 0, 0 };
-
-static const WCHAR wszTiffCompressionMethod[] = {'T','i','f','f','C','o','m','p','r','e','s','s','i','o','n','M','e','t','h','o','d',0};
-static const WCHAR wszCompressionQuality[] = {'C','o','m','p','r','e','s','s','i','o','n','Q','u','a','l','i','t','y',0};
-
-static void *libtiff_handle;
-#define MAKE_FUNCPTR(f) static typeof(f) * p##f
-MAKE_FUNCPTR(TIFFClientOpen);
-MAKE_FUNCPTR(TIFFClose);
-MAKE_FUNCPTR(TIFFCurrentDirOffset);
-MAKE_FUNCPTR(TIFFGetField);
-MAKE_FUNCPTR(TIFFIsByteSwapped);
-MAKE_FUNCPTR(TIFFNumberOfDirectories);
-MAKE_FUNCPTR(TIFFReadDirectory);
-MAKE_FUNCPTR(TIFFReadEncodedStrip);
-MAKE_FUNCPTR(TIFFReadEncodedTile);
-MAKE_FUNCPTR(TIFFSetDirectory);
-MAKE_FUNCPTR(TIFFSetField);
-MAKE_FUNCPTR(TIFFWriteDirectory);
-MAKE_FUNCPTR(TIFFWriteScanline);
-#undef MAKE_FUNCPTR
-
-static void *load_libtiff(void)
-{
- void *result;
-
- EnterCriticalSection(&init_tiff_cs);
-
- if (!libtiff_handle &&
- (libtiff_handle = dlopen(SONAME_LIBTIFF, RTLD_NOW)) != NULL)
- {
- void * (*pTIFFSetWarningHandler)(void *);
- void * (*pTIFFSetWarningHandlerExt)(void *);
-
-#define LOAD_FUNCPTR(f) \
- if((p##f = dlsym(libtiff_handle, #f)) == NULL) { \
- ERR("failed to load symbol %s\n", #f); \
- libtiff_handle = NULL; \
- LeaveCriticalSection(&init_tiff_cs); \
- return NULL; \
- }
- LOAD_FUNCPTR(TIFFClientOpen);
- LOAD_FUNCPTR(TIFFClose);
- LOAD_FUNCPTR(TIFFCurrentDirOffset);
- LOAD_FUNCPTR(TIFFGetField);
- LOAD_FUNCPTR(TIFFIsByteSwapped);
- LOAD_FUNCPTR(TIFFNumberOfDirectories);
- LOAD_FUNCPTR(TIFFReadDirectory);
- LOAD_FUNCPTR(TIFFReadEncodedStrip);
- LOAD_FUNCPTR(TIFFReadEncodedTile);
- LOAD_FUNCPTR(TIFFSetDirectory);
- LOAD_FUNCPTR(TIFFSetField);
- LOAD_FUNCPTR(TIFFWriteDirectory);
- LOAD_FUNCPTR(TIFFWriteScanline);
-#undef LOAD_FUNCPTR
-
- if ((pTIFFSetWarningHandler = dlsym(libtiff_handle, "TIFFSetWarningHandler")))
- pTIFFSetWarningHandler(NULL);
- if ((pTIFFSetWarningHandlerExt = dlsym(libtiff_handle, "TIFFSetWarningHandlerExt")))
- pTIFFSetWarningHandlerExt(NULL);
- }
-
- result = libtiff_handle;
-
- LeaveCriticalSection(&init_tiff_cs);
- return result;
-}
-
-static tsize_t tiff_stream_read(thandle_t client_data, tdata_t data, tsize_t size)
-{
- IStream *stream = (IStream*)client_data;
- ULONG bytes_read;
- HRESULT hr;
-
- hr = IStream_Read(stream, data, size, &bytes_read);
- if (FAILED(hr)) bytes_read = 0;
- return bytes_read;
-}
-
-static tsize_t tiff_stream_write(thandle_t client_data, tdata_t data, tsize_t size)
-{
- IStream *stream = (IStream*)client_data;
- ULONG bytes_written;
- HRESULT hr;
-
- hr = IStream_Write(stream, data, size, &bytes_written);
- if (FAILED(hr)) bytes_written = 0;
- return bytes_written;
-}
-
-static toff_t tiff_stream_seek(thandle_t client_data, toff_t offset, int whence)
-{
- IStream *stream = (IStream*)client_data;
- LARGE_INTEGER move;
- DWORD origin;
- ULARGE_INTEGER new_position;
- HRESULT hr;
-
- move.QuadPart = offset;
- switch (whence)
- {
- case SEEK_SET:
- origin = STREAM_SEEK_SET;
- break;
- case SEEK_CUR:
- origin = STREAM_SEEK_CUR;
- break;
- case SEEK_END:
- origin = STREAM_SEEK_END;
- break;
- default:
- ERR("unknown whence value %i\n", whence);
- return -1;
- }
-
- hr = IStream_Seek(stream, move, origin, &new_position);
- if (SUCCEEDED(hr)) return new_position.QuadPart;
- else return -1;
-}
-
-static int tiff_stream_close(thandle_t client_data)
-{
- /* Caller is responsible for releasing the stream object. */
- return 0;
-}
-
-static toff_t tiff_stream_size(thandle_t client_data)
-{
- IStream *stream = (IStream*)client_data;
- STATSTG statstg;
- HRESULT hr;
-
- hr = IStream_Stat(stream, &statstg, STATFLAG_NONAME);
-
- if (SUCCEEDED(hr)) return statstg.cbSize.QuadPart;
- else return -1;
-}
-
-static int tiff_stream_map(thandle_t client_data, tdata_t *addr, toff_t *size)
-{
- /* Cannot mmap streams */
- return 0;
-}
-
-static void tiff_stream_unmap(thandle_t client_data, tdata_t addr, toff_t size)
-{
- /* No need to ever do this, since we can't map things. */
-}
-
-static TIFF* tiff_open_stream(IStream *stream, const char *mode)
-{
- LARGE_INTEGER zero;
-
- zero.QuadPart = 0;
- IStream_Seek(stream, zero, STREAM_SEEK_SET, NULL);
-
- return pTIFFClientOpen("<IStream object>", mode, stream, tiff_stream_read,
- tiff_stream_write, (void *)tiff_stream_seek, tiff_stream_close,
- (void *)tiff_stream_size, (void *)tiff_stream_map, (void *)tiff_stream_unmap);
-}
-
-struct tiff_encode_format {
- const WICPixelFormatGUID *guid;
- int photometric;
- int bps;
- int samples;
- int bpp;
- int extra_sample;
- int extra_sample_type;
- int reverse_bgr;
-};
-
-static const struct tiff_encode_format formats[] = {
- {&GUID_WICPixelFormat24bppBGR, 2, 8, 3, 24, 0, 0, 1},
- {&GUID_WICPixelFormat24bppRGB, 2, 8, 3, 24, 0, 0, 0},
- {&GUID_WICPixelFormatBlackWhite, 1, 1, 1, 1, 0, 0, 0},
- {&GUID_WICPixelFormat4bppGray, 1, 4, 1, 4, 0, 0, 0},
- {&GUID_WICPixelFormat8bppGray, 1, 8, 1, 8, 0, 0, 0},
- {&GUID_WICPixelFormat32bppBGRA, 2, 8, 4, 32, 1, 2, 1},
- {&GUID_WICPixelFormat32bppPBGRA, 2, 8, 4, 32, 1, 1, 1},
- {&GUID_WICPixelFormat48bppRGB, 2, 16, 3, 48, 0, 0, 0},
- {&GUID_WICPixelFormat64bppRGBA, 2, 16, 4, 64, 1, 2, 0},
- {&GUID_WICPixelFormat64bppPRGBA, 2, 16, 4, 64, 1, 1, 0},
- {&GUID_WICPixelFormat1bppIndexed, 3, 1, 1, 1, 0, 0, 0},
- {&GUID_WICPixelFormat4bppIndexed, 3, 4, 1, 4, 0, 0, 0},
- {&GUID_WICPixelFormat8bppIndexed, 3, 8, 1, 8, 0, 0, 0},
- {0}
-};
-
-typedef struct TiffEncoder {
- IWICBitmapEncoder IWICBitmapEncoder_iface;
- LONG ref;
- IStream *stream;
- CRITICAL_SECTION lock; /* Must be held when tiff is used or fields below are set */
- TIFF *tiff;
- BOOL initialized;
- BOOL committed;
- ULONG num_frames;
- ULONG num_frames_committed;
-} TiffEncoder;
-
-static inline TiffEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface)
-{
- return CONTAINING_RECORD(iface, TiffEncoder, IWICBitmapEncoder_iface);
-}
-
-typedef struct TiffFrameEncode {
- IWICBitmapFrameEncode IWICBitmapFrameEncode_iface;
- LONG ref;
- TiffEncoder *parent;
- /* fields below are protected by parent->lock */
- BOOL initialized;
- BOOL info_written;
- BOOL committed;
- const struct tiff_encode_format *format;
- UINT width, height;
- double xres, yres;
- UINT lines_written;
- WICColor palette[256];
- UINT colors;
-} TiffFrameEncode;
-
-static inline TiffFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface)
-{
- return CONTAINING_RECORD(iface, TiffFrameEncode, IWICBitmapFrameEncode_iface);
-}
-
-static HRESULT WINAPI TiffFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid,
- void **ppv)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
-
- if (!ppv) return E_INVALIDARG;
-
- if (IsEqualIID(&IID_IUnknown, iid) ||
- IsEqualIID(&IID_IWICBitmapFrameEncode, iid))
- {
- *ppv = &This->IWICBitmapFrameEncode_iface;
- }
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
-}
-
-static ULONG WINAPI TiffFrameEncode_AddRef(IWICBitmapFrameEncode *iface)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) refcount=%u\n", iface, ref);
-
- return ref;
-}
-
-static ULONG WINAPI TiffFrameEncode_Release(IWICBitmapFrameEncode *iface)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
-
- TRACE("(%p) refcount=%u\n", iface, ref);
-
- if (ref == 0)
- {
- IWICBitmapEncoder_Release(&This->parent->IWICBitmapEncoder_iface);
- HeapFree(GetProcessHeap(), 0, This);
- }
-
- return ref;
-}
-
-static HRESULT WINAPI TiffFrameEncode_Initialize(IWICBitmapFrameEncode *iface,
- IPropertyBag2 *pIEncoderOptions)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("(%p,%p)\n", iface, pIEncoderOptions);
-
- EnterCriticalSection(&This->parent->lock);
-
- if (This->initialized)
- {
- LeaveCriticalSection(&This->parent->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- This->initialized = TRUE;
-
- LeaveCriticalSection(&This->parent->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TiffFrameEncode_SetSize(IWICBitmapFrameEncode *iface,
- UINT uiWidth, UINT uiHeight)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("(%p,%u,%u)\n", iface, uiWidth, uiHeight);
-
- EnterCriticalSection(&This->parent->lock);
-
- if (!This->initialized || This->info_written)
- {
- LeaveCriticalSection(&This->parent->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- This->width = uiWidth;
- This->height = uiHeight;
-
- LeaveCriticalSection(&This->parent->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TiffFrameEncode_SetResolution(IWICBitmapFrameEncode *iface,
- double dpiX, double dpiY)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- TRACE("(%p,%0.2f,%0.2f)\n", iface, dpiX, dpiY);
-
- EnterCriticalSection(&This->parent->lock);
-
- if (!This->initialized || This->info_written)
- {
- LeaveCriticalSection(&This->parent->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- This->xres = dpiX;
- This->yres = dpiY;
-
- LeaveCriticalSection(&This->parent->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TiffFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface,
- WICPixelFormatGUID *pPixelFormat)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- int i;
-
- TRACE("(%p,%s)\n", iface, debugstr_guid(pPixelFormat));
-
- EnterCriticalSection(&This->parent->lock);
-
- if (!This->initialized || This->info_written)
- {
- LeaveCriticalSection(&This->parent->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormat2bppIndexed))
- *pPixelFormat = GUID_WICPixelFormat4bppIndexed;
-
- for (i=0; formats[i].guid; i++)
- {
- if (IsEqualGUID(formats[i].guid, pPixelFormat))
- break;
- }
-
- if (!formats[i].guid) i = 0;
-
- This->format = &formats[i];
- memcpy(pPixelFormat, This->format->guid, sizeof(GUID));
-
- LeaveCriticalSection(&This->parent->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TiffFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface,
- UINT cCount, IWICColorContext **ppIColorContext)
-{
- FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TiffFrameEncode_SetPalette(IWICBitmapFrameEncode *iface,
- IWICPalette *palette)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- HRESULT hr;
-
- TRACE("(%p,%p)\n", iface, palette);
-
- if (!palette) return E_INVALIDARG;
-
- EnterCriticalSection(&This->parent->lock);
-
- if (This->initialized)
- hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors);
- else
- hr = WINCODEC_ERR_NOTINITIALIZED;
-
- LeaveCriticalSection(&This->parent->lock);
- return hr;
-}
-
-static HRESULT WINAPI TiffFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface,
- IWICBitmapSource *pIThumbnail)
-{
- FIXME("(%p,%p): stub\n", iface, pIThumbnail);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI TiffFrameEncode_WritePixels(IWICBitmapFrameEncode *iface,
- UINT lineCount, UINT cbStride, UINT cbBufferSize, BYTE *pbPixels)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- BYTE *row_data, *swapped_data = NULL;
- UINT i, j, line_size;
-
- TRACE("(%p,%u,%u,%u,%p)\n", iface, lineCount, cbStride, cbBufferSize, pbPixels);
-
- EnterCriticalSection(&This->parent->lock);
-
- if (!This->initialized || !This->width || !This->height || !This->format)
- {
- LeaveCriticalSection(&This->parent->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- if (lineCount == 0 || lineCount + This->lines_written > This->height)
- {
- LeaveCriticalSection(&This->parent->lock);
- return E_INVALIDARG;
- }
-
- line_size = ((This->width * This->format->bpp)+7)/8;
-
- if (This->format->reverse_bgr)
- {
- swapped_data = HeapAlloc(GetProcessHeap(), 0, line_size);
- if (!swapped_data)
- {
- LeaveCriticalSection(&This->parent->lock);
- return E_OUTOFMEMORY;
- }
- }
-
- if (!This->info_written)
- {
- pTIFFSetField(This->parent->tiff, TIFFTAG_PHOTOMETRIC, (uint16)This->format->photometric);
- pTIFFSetField(This->parent->tiff, TIFFTAG_PLANARCONFIG, (uint16)1);
- pTIFFSetField(This->parent->tiff, TIFFTAG_BITSPERSAMPLE, (uint16)This->format->bps);
- pTIFFSetField(This->parent->tiff, TIFFTAG_SAMPLESPERPIXEL, (uint16)This->format->samples);
-
- if (This->format->extra_sample)
- {
- uint16 extra_samples;
- extra_samples = This->format->extra_sample_type;
-
- pTIFFSetField(This->parent->tiff, TIFFTAG_EXTRASAMPLES, (uint16)1, &extra_samples);
- }
-
- pTIFFSetField(This->parent->tiff, TIFFTAG_IMAGEWIDTH, (uint32)This->width);
- pTIFFSetField(This->parent->tiff, TIFFTAG_IMAGELENGTH, (uint32)This->height);
-
- if (This->xres != 0.0 && This->yres != 0.0)
- {
- pTIFFSetField(This->parent->tiff, TIFFTAG_RESOLUTIONUNIT, (uint16)2); /* Inch */
- pTIFFSetField(This->parent->tiff, TIFFTAG_XRESOLUTION, (float)This->xres);
- pTIFFSetField(This->parent->tiff, TIFFTAG_YRESOLUTION, (float)This->yres);
- }
-
- if (This->format->bpp <= 8 && This->colors && !IsEqualGUID(This->format->guid, &GUID_WICPixelFormatBlackWhite))
- {
- uint16 red[256], green[256], blue[256];
- UINT i;
-
- for (i = 0; i < This->colors; i++)
- {
- red[i] = (This->palette[i] >> 8) & 0xff00;
- green[i] = This->palette[i] & 0xff00;
- blue[i] = (This->palette[i] << 8) & 0xff00;
- }
-
- pTIFFSetField(This->parent->tiff, TIFFTAG_COLORMAP, red, green, blue);
- }
-
- This->info_written = TRUE;
- }
-
- for (i=0; i<lineCount; i++)
- {
- row_data = pbPixels + i * cbStride;
-
- if (This->format->reverse_bgr && This->format->bps == 8)
- {
- memcpy(swapped_data, row_data, line_size);
- for (j=0; j<line_size; j += This->format->samples)
- {
- BYTE temp;
- temp = swapped_data[j];
- swapped_data[j] = swapped_data[j+2];
- swapped_data[j+2] = temp;
- }
- row_data = swapped_data;
- }
-
- pTIFFWriteScanline(This->parent->tiff, (tdata_t)row_data, i+This->lines_written, 0);
- }
-
- This->lines_written += lineCount;
-
- LeaveCriticalSection(&This->parent->lock);
-
- HeapFree(GetProcessHeap(), 0, swapped_data);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TiffFrameEncode_WriteSource(IWICBitmapFrameEncode *iface,
- IWICBitmapSource *pIBitmapSource, WICRect *prc)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
- HRESULT hr;
-
- TRACE("(%p,%p,%s)\n", iface, pIBitmapSource, debug_wic_rect(prc));
-
- if (!This->initialized)
- return WINCODEC_ERR_WRONGSTATE;
-
- hr = configure_write_source(iface, pIBitmapSource, prc,
- This->format ? This->format->guid : NULL, This->width, This->height,
- This->xres, This->yres);
-
- if (SUCCEEDED(hr))
- {
- hr = write_source(iface, pIBitmapSource, prc,
- This->format->guid, This->format->bpp,
- !This->colors && This->format->bpp <= 8 && !IsEqualGUID(This->format->guid, &GUID_WICPixelFormatBlackWhite),
- This->width, This->height);
- }
-
- return hr;
-}
-
-static HRESULT WINAPI TiffFrameEncode_Commit(IWICBitmapFrameEncode *iface)
-{
- TiffFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface);
-
- TRACE("(%p)\n", iface);
-
- EnterCriticalSection(&This->parent->lock);
-
- if (!This->info_written || This->lines_written != This->height || This->committed)
- {
- LeaveCriticalSection(&This->parent->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- /* libtiff will commit the data when creating a new frame or closing the file */
-
- This->committed = TRUE;
- This->parent->num_frames_committed++;
-
- LeaveCriticalSection(&This->parent->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TiffFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface,
- IWICMetadataQueryWriter **ppIMetadataQueryWriter)
-{
- FIXME("(%p, %p): stub\n", iface, ppIMetadataQueryWriter);
- return E_NOTIMPL;
-}
-
-static const IWICBitmapFrameEncodeVtbl TiffFrameEncode_Vtbl = {
- TiffFrameEncode_QueryInterface,
- TiffFrameEncode_AddRef,
- TiffFrameEncode_Release,
- TiffFrameEncode_Initialize,
- TiffFrameEncode_SetSize,
- TiffFrameEncode_SetResolution,
- TiffFrameEncode_SetPixelFormat,
- TiffFrameEncode_SetColorContexts,
- TiffFrameEncode_SetPalette,
- TiffFrameEncode_SetThumbnail,
- TiffFrameEncode_WritePixels,
- TiffFrameEncode_WriteSource,
- TiffFrameEncode_Commit,
- TiffFrameEncode_GetMetadataQueryWriter
-};
-
-static HRESULT WINAPI TiffEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid,
- void **ppv)
-{
- TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
- TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv);
-
- if (!ppv) return E_INVALIDARG;
-
- if (IsEqualIID(&IID_IUnknown, iid) ||
- IsEqualIID(&IID_IWICBitmapEncoder, iid))
- {
- *ppv = &This->IWICBitmapEncoder_iface;
- }
- else
- {
- *ppv = NULL;
- return E_NOINTERFACE;
- }
-
- IUnknown_AddRef((IUnknown*)*ppv);
- return S_OK;
-}
-
-static ULONG WINAPI TiffEncoder_AddRef(IWICBitmapEncoder *iface)
-{
- TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
- ULONG ref = InterlockedIncrement(&This->ref);
-
- TRACE("(%p) refcount=%u\n", iface, ref);
-
- return ref;
-}
-
-static ULONG WINAPI TiffEncoder_Release(IWICBitmapEncoder *iface)
-{
- TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
- ULONG ref = InterlockedDecrement(&This->ref);
-
- TRACE("(%p) refcount=%u\n", iface, ref);
-
- if (ref == 0)
- {
- if (This->tiff) pTIFFClose(This->tiff);
- if (This->stream) IStream_Release(This->stream);
- This->lock.DebugInfo->Spare[0] = 0;
- DeleteCriticalSection(&This->lock);
- HeapFree(GetProcessHeap(), 0, This);
- }
-
- return ref;
-}
-
-static HRESULT WINAPI TiffEncoder_Initialize(IWICBitmapEncoder *iface,
- IStream *pIStream, WICBitmapEncoderCacheOption cacheOption)
-{
- TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
- TIFF *tiff;
- HRESULT hr=S_OK;
-
- TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOption);
-
- EnterCriticalSection(&This->lock);
-
- if (This->initialized || This->committed)
- {
- hr = WINCODEC_ERR_WRONGSTATE;
- goto exit;
- }
-
- tiff = tiff_open_stream(pIStream, "w");
-
- if (!tiff)
- {
- hr = E_FAIL;
- goto exit;
- }
-
- This->tiff = tiff;
- This->stream = pIStream;
- IStream_AddRef(pIStream);
- This->initialized = TRUE;
-
-exit:
- LeaveCriticalSection(&This->lock);
- return hr;
-}
-
-static HRESULT WINAPI TiffEncoder_GetContainerFormat(IWICBitmapEncoder *iface,
- GUID *pguidContainerFormat)
-{
- TRACE("(%p,%p)\n", iface, pguidContainerFormat);
-
- if (!pguidContainerFormat)
- return E_INVALIDARG;
-
- memcpy(pguidContainerFormat, &GUID_ContainerFormatTiff, sizeof(GUID));
- return S_OK;
-}
-
-static HRESULT WINAPI TiffEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info)
-{
- IWICComponentInfo *comp_info;
- HRESULT hr;
-
- TRACE("%p,%p\n", iface, info);
-
- if (!info) return E_INVALIDARG;
-
- hr = CreateComponentInfo(&CLSID_WICTiffEncoder, &comp_info);
- if (hr == S_OK)
- {
- hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info);
- IWICComponentInfo_Release(comp_info);
- }
- return hr;
-}
-
-static HRESULT WINAPI TiffEncoder_SetColorContexts(IWICBitmapEncoder *iface,
- UINT cCount, IWICColorContext **ppIColorContext)
-{
- FIXME("(%p,%u,%p): stub\n", iface, cCount, ppIColorContext);
- return E_NOTIMPL;
-}
-
-static HRESULT WINAPI TiffEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette)
-{
- TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
- HRESULT hr;
-
- TRACE("(%p,%p)\n", iface, palette);
-
- EnterCriticalSection(&This->lock);
-
- hr = This->stream ? WINCODEC_ERR_UNSUPPORTEDOPERATION : WINCODEC_ERR_NOTINITIALIZED;
-
- LeaveCriticalSection(&This->lock);
-
- return hr;
-}
-
-static HRESULT WINAPI TiffEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *pIThumbnail)
-{
- TRACE("(%p,%p)\n", iface, pIThumbnail);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI TiffEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *pIPreview)
-{
- TRACE("(%p,%p)\n", iface, pIPreview);
- return WINCODEC_ERR_UNSUPPORTEDOPERATION;
-}
-
-static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface,
- IWICBitmapFrameEncode **ppIFrameEncode, IPropertyBag2 **ppIEncoderOptions)
-{
- TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
- TiffFrameEncode *result;
- static const PROPBAG2 opts[2] =
- {
- { PROPBAG2_TYPE_DATA, VT_UI1, 0, 0, (LPOLESTR)wszTiffCompressionMethod },
- { PROPBAG2_TYPE_DATA, VT_R4, 0, 0, (LPOLESTR)wszCompressionQuality },
- };
- HRESULT hr=S_OK;
-
- TRACE("(%p,%p,%p)\n", iface, ppIFrameEncode, ppIEncoderOptions);
-
- EnterCriticalSection(&This->lock);
-
- if (!This->initialized || This->committed)
- {
- hr = WINCODEC_ERR_WRONGSTATE;
- }
- else if (This->num_frames != This->num_frames_committed)
- {
- FIXME("New frame created before previous frame was committed\n");
- hr = E_FAIL;
- }
-
- if (ppIEncoderOptions && SUCCEEDED(hr))
- {
- hr = CreatePropertyBag2(opts, ARRAY_SIZE(opts), ppIEncoderOptions);
- if (SUCCEEDED(hr))
- {
- VARIANT v;
- VariantInit(&v);
- V_VT(&v) = VT_UI1;
- V_UI1(&v) = WICTiffCompressionDontCare;
- hr = IPropertyBag2_Write(*ppIEncoderOptions, 1, (PROPBAG2 *)opts, &v);
- VariantClear(&v);
- if (FAILED(hr))
- {
- IPropertyBag2_Release(*ppIEncoderOptions);
- *ppIEncoderOptions = NULL;
- }
- }
- }
-
- if (SUCCEEDED(hr))
- {
- result = HeapAlloc(GetProcessHeap(), 0, sizeof(*result));
-
- if (result)
- {
- result->IWICBitmapFrameEncode_iface.lpVtbl = &TiffFrameEncode_Vtbl;
- result->ref = 1;
- result->parent = This;
- result->initialized = FALSE;
- result->info_written = FALSE;
- result->committed = FALSE;
- result->format = NULL;
- result->width = 0;
- result->height = 0;
- result->xres = 0.0;
- result->yres = 0.0;
- result->lines_written = 0;
- result->colors = 0;
-
- IWICBitmapEncoder_AddRef(iface);
- *ppIFrameEncode = &result->IWICBitmapFrameEncode_iface;
-
- if (This->num_frames != 0)
- pTIFFWriteDirectory(This->tiff);
-
- This->num_frames++;
- }
- else
- hr = E_OUTOFMEMORY;
-
- if (FAILED(hr))
- {
- IPropertyBag2_Release(*ppIEncoderOptions);
- *ppIEncoderOptions = NULL;
- }
- }
-
- LeaveCriticalSection(&This->lock);
-
- return hr;
-}
-
-static HRESULT WINAPI TiffEncoder_Commit(IWICBitmapEncoder *iface)
-{
- TiffEncoder *This = impl_from_IWICBitmapEncoder(iface);
-
- TRACE("(%p)\n", iface);
-
- EnterCriticalSection(&This->lock);
-
- if (!This->initialized || This->committed)
- {
- LeaveCriticalSection(&This->lock);
- return WINCODEC_ERR_WRONGSTATE;
- }
-
- pTIFFClose(This->tiff);
- IStream_Release(This->stream);
- This->stream = NULL;
- This->tiff = NULL;
-
- This->committed = TRUE;
-
- LeaveCriticalSection(&This->lock);
-
- return S_OK;
-}
-
-static HRESULT WINAPI TiffEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface,
- IWICMetadataQueryWriter **ppIMetadataQueryWriter)
-{
- FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryWriter);
- return E_NOTIMPL;
-}
-
-static const IWICBitmapEncoderVtbl TiffEncoder_Vtbl = {
- TiffEncoder_QueryInterface,
- TiffEncoder_AddRef,
- TiffEncoder_Release,
- TiffEncoder_Initialize,
- TiffEncoder_GetContainerFormat,
- TiffEncoder_GetEncoderInfo,
- TiffEncoder_SetColorContexts,
- TiffEncoder_SetPalette,
- TiffEncoder_SetThumbnail,
- TiffEncoder_SetPreview,
- TiffEncoder_CreateNewFrame,
- TiffEncoder_Commit,
- TiffEncoder_GetMetadataQueryWriter
-};
-
-HRESULT TiffEncoder_CreateInstance(REFIID iid, void** ppv)
-{
- TiffEncoder *This;
- HRESULT ret;
-
- TRACE("(%s,%p)\n", debugstr_guid(iid), ppv);
-
- *ppv = NULL;
-
- if (!load_libtiff())
- {
- ERR("Failed writing TIFF because unable to load %s\n",SONAME_LIBTIFF);
- return E_FAIL;
- }
-
- This = HeapAlloc(GetProcessHeap(), 0, sizeof(TiffEncoder));
- if (!This) return E_OUTOFMEMORY;
-
- This->IWICBitmapEncoder_iface.lpVtbl = &TiffEncoder_Vtbl;
- This->ref = 1;
- This->stream = NULL;
- InitializeCriticalSection(&This->lock);
- This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": TiffEncoder.lock");
- This->tiff = NULL;
- This->initialized = FALSE;
- This->num_frames = 0;
- This->num_frames_committed = 0;
- This->committed = FALSE;
-
- ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv);
- IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface);
-
- return ret;
-}
-
-#else /* !SONAME_LIBTIFF */
-
-HRESULT TiffEncoder_CreateInstance(REFIID iid, void** ppv)
-{
- ERR("Trying to save TIFF picture, but Wine was compiled without TIFF support.\n");
- return E_FAIL;
-}
-
-#endif
-
-HRESULT TiffDecoder_CreateInstance(REFIID iid, void** ppv)
-{
- HRESULT hr;
- struct decoder *decoder;
- struct decoder_info decoder_info;
-
- hr = get_unix_decoder(&CLSID_WICTiffDecoder, &decoder_info, &decoder);
-
- if (SUCCEEDED(hr))
- hr = CommonDecoder_CreateInstance(decoder, &decoder_info, iid, ppv);
-
- return hr;
-}
diff --git a/dlls/windowscodecs/unix_lib.c b/dlls/windowscodecs/unix_lib.c
index 7fc5f388697..7101880b93c 100644
--- a/dlls/windowscodecs/unix_lib.c
+++ b/dlls/windowscodecs/unix_lib.c
@@ -86,6 +86,9 @@ HRESULT CDECL encoder_create(const CLSID *encoder_clsid, struct encoder_info *in
if (IsEqualGUID(encoder_clsid, &CLSID_WICPngEncoder))
return png_encoder_create(info, result);
+ if (IsEqualGUID(encoder_clsid, &CLSID_WICTiffEncoder))
+ return tiff_encoder_create(info, result);
+
return E_NOTIMPL;
}
diff --git a/dlls/windowscodecs/wincodecs_private.h b/dlls/windowscodecs/wincodecs_private.h
index a3d5f5591b0..ab0329b8bb3 100644
--- a/dlls/windowscodecs/wincodecs_private.h
+++ b/dlls/windowscodecs/wincodecs_private.h
@@ -341,6 +341,8 @@ enum encoder_option
{
ENCODER_OPTION_INTERLACE,
ENCODER_OPTION_FILTER,
+ ENCODER_OPTION_COMPRESSION_METHOD,
+ ENCODER_OPTION_COMPRESSION_QUALITY,
ENCODER_OPTION_END
};
@@ -397,6 +399,7 @@ HRESULT CDECL tiff_decoder_create(struct decoder_info *info, struct decoder **re
HRESULT CDECL jpeg_decoder_create(struct decoder_info *info, struct decoder **result);
HRESULT CDECL png_encoder_create(struct encoder_info *info, struct encoder **result);
+HRESULT CDECL tiff_encoder_create(struct encoder_info *info, struct encoder **result);
struct unix_funcs
{
--
2.17.1
1
0
Nov. 20, 2020
Have the winebuild -spec.o include an undefined .globl referencing
symbols we know the winecrt0 entry point will eventually reference,
so ld knows about what it needs before scanning library archives.
Signed-off-by: Kevin Puetz <PuetzKevinA(a)JohnDeere.com>
---
This one had fuzz in spec32.c from d5c089f5fa71e2ae568b2f1bcb9158223c552040
Still applied correctly, but marvin apparently doesn't like fuzz. Oops.
---
wine.exe.so files set __wine_spec_exe_entry as the entry point.
Therefore the linker is not initially looking for main and will pass
over objects in lib.a archives that might provide it. When it gets to
libwinecrt0.a is reached, it finds __wine_spec_exe_entry and learns
that this wants main, but the resulting rescan will find the winecrt0
definition in terms of WinMain, before rescanning earlier libraries.
So only a direct .o file (which is never passed over) can override
the winecrt0 definition, and libraries like -lgtest_main do not work.
---
tools/winebuild/build.h | 2 ++
tools/winebuild/main.c | 22 ++++++++++++++++++++--
tools/winebuild/spec32.c | 12 ++++++++++++
tools/winegcc/winegcc.c | 4 ++--
4 files changed, 36 insertions(+), 4 deletions(-)
diff --git a/tools/winebuild/build.h b/tools/winebuild/build.h
index 03715af9563..a4b9bc97e3e 100644
--- a/tools/winebuild/build.h
+++ b/tools/winebuild/build.h
@@ -136,6 +136,7 @@ typedef struct
int subsystem; /* subsystem id */
int subsystem_major; /* subsystem version major number */
int subsystem_minor; /* subsystem version minor number */
+ int unicode_app; /* default to unicode entry point */
ORDDEF *entry_points; /* dll entry points */
ORDDEF **names; /* array of entry point names (points into entry_points) */
ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */
@@ -299,6 +300,7 @@ extern void output_gnu_stack_note(void);
extern void add_import_dll( const char *name, const char *filename );
extern void add_delayed_import( const char *name );
extern void add_extra_ld_symbol( const char *name );
+extern void add_spec_extra_ld_symbol( const char *name );
extern void read_undef_symbols( DLLSPEC *spec, char **argv );
extern void resolve_imports( DLLSPEC *spec );
extern int is_undefined( const char *name );
diff --git a/tools/winebuild/main.c b/tools/winebuild/main.c
index 0e5e1627dda..68137b0f4c2 100644
--- a/tools/winebuild/main.c
+++ b/tools/winebuild/main.c
@@ -396,8 +396,25 @@ static const char *get_default_entry_point( const DLLSPEC *spec )
{
if (spec->characteristics & IMAGE_FILE_DLL) return "DllMain";
if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry";
- if (spec->type == SPEC_WIN16) return "__wine_spec_exe16_entry";
- return "__wine_spec_exe_entry";
+ if (spec->type == SPEC_WIN16) {
+ add_spec_extra_ld_symbol("WinMain16");
+ return "__wine_spec_exe16_entry";
+ }
+ if (spec->unicode_app) {
+ /* __wine_spec_exe_wentry always calls wmain */
+ add_spec_extra_ld_symbol("wmain");
+ if(spec->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
+ add_spec_extra_ld_symbol("wWinMain");
+ }
+ return "__wine_spec_exe_wentry";
+ } else {
+ /* __wine_spec_exe_entry always calls main */
+ add_spec_extra_ld_symbol("main");
+ if(spec->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
+ add_spec_extra_ld_symbol("WinMain");
+ }
+ return "__wine_spec_exe_entry";
+ }
}
/* parse options from the argv array and remove all the recognized ones */
@@ -448,6 +465,7 @@ static char **parse_options( int argc, char **argv, DLLSPEC *spec )
else if (!strcmp( optarg, "thumb" )) thumb_mode = 1;
else if (!strcmp( optarg, "no-cygwin" )) use_msvcrt = 1;
else if (!strcmp( optarg, "unix" )) unix_lib = 1;
+ else if (!strcmp( optarg, "unicode" )) spec->unicode_app = 1;
else if (!strncmp( optarg, "cpu=", 4 )) cpu_option = xstrdup( optarg + 4 );
else if (!strncmp( optarg, "fpu=", 4 )) fpu_option = xstrdup( optarg + 4 );
else if (!strncmp( optarg, "arch=", 5 )) arch_option = xstrdup( optarg + 5 );
diff --git a/tools/winebuild/spec32.c b/tools/winebuild/spec32.c
index ba2edfb588f..a12e7d38aac 100644
--- a/tools/winebuild/spec32.c
+++ b/tools/winebuild/spec32.c
@@ -50,6 +50,13 @@ int needs_get_pc_thunk = 0;
static const char builtin_signature[32] = "Wine builtin DLL";
static const char fakedll_signature[32] = "Wine placeholder DLL";
+static struct strarray spec_extra_ld_symbols = { 0 }; /* list of extra symbols that ld should resolve */
+
+/* add a symbol to the list of extra symbols that ld must resolve */
+void add_spec_extra_ld_symbol( const char *name )
+{
+ strarray_add( &spec_extra_ld_symbols, name, NULL );
+}
static unsigned int hash_filename( const char *name )
{
@@ -610,6 +617,7 @@ void output_exports( DLLSPEC *spec )
void output_module( DLLSPEC *spec )
{
int machine = 0;
+ int i;
unsigned int page_size = get_page_size();
const char *data_dirs[16] = { NULL };
@@ -688,6 +696,10 @@ void output_module( DLLSPEC *spec )
output( "\t.long 0\n" ); /* SizeOfCode */
output( "\t.long 0\n" ); /* SizeOfInitializedData */
output( "\t.long 0\n" ); /* SizeOfUninitializedData */
+
+ for (i = 0; i < spec_extra_ld_symbols.count; i++)
+ output( "\t.globl %s\n", asm_name(spec_extra_ld_symbols.str[i]) );
+
/* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
output( "\t%s %s\n", /* AddressOfEntryPoint */
get_asm_ptr_keyword(), spec->init_func ? asm_name(spec->init_func) : "0" );
diff --git a/tools/winegcc/winegcc.c b/tools/winegcc/winegcc.c
index 9268a5dfd1d..cef0832455c 100644
--- a/tools/winegcc/winegcc.c
+++ b/tools/winegcc/winegcc.c
@@ -1245,8 +1245,6 @@ static void build(struct options* opts)
entry_point = (is_pe && opts->target_cpu == CPU_x86) ? "DriverEntry(a)8" : "DriverEntry";
else if (opts->use_msvcrt && !opts->shared && !opts->win16_app)
entry_point = opts->unicode_app ? "wmainCRTStartup" : "mainCRTStartup";
- else if (!is_pe && !opts->shared && opts->unicode_app)
- entry_point = "__wine_spec_exe_wentry";
}
else entry_point = opts->entry_point;
@@ -1258,6 +1256,8 @@ static void build(struct options* opts)
spec_o_name = get_temp_file(output_name, ".spec.o");
if (opts->force_pointer_size)
strarray_add(spec_args, strmake("-m%u", 8 * opts->force_pointer_size ));
+ if(opts->unicode_app)
+ strarray_add(spec_args, "-municode");
strarray_add(spec_args, "-D_REENTRANT");
if (opts->pic && !is_pe) strarray_add(spec_args, "-fPIC");
strarray_add(spec_args, opts->shared ? "--dll" : "--exe");
1
0
Nov. 20, 2020
Have the winebuild -spec.o include an undefined .globl referencing
symbols we know the winecrt0 entry point will eventually reference,
so ld knows about what it needs before scanning library archives.
---
wine.exe.so files set __wine_spec_exe_entry as the entry point.
Therefore the linker is not initially looking for main and will pass
over objects in lib.a archives that might provide it. When it gets to
libwinecrt0.a is reached, it finds __wine_spec_exe_entry and learns
that this wants main, but the resulting rescan will find the winecrt0
definition in terms of WinMain, before rescanning earlier libraries.
So only a direct .o file (which is never passed over) can override
the winecrt0 definition, and libraries like -lgtest_main do not work.
Index: wine/tools/winebuild/build.h
===================================================================
--- wine.orig/tools/winebuild/build.h
+++ wine/tools/winebuild/build.h
@@ -136,6 +136,7 @@ typedef struct
int subsystem; /* subsystem id */
int subsystem_major; /* subsystem version major number */
int subsystem_minor; /* subsystem version minor number */
+ int unicode_app; /* default to unicode entry point */
ORDDEF *entry_points; /* dll entry points */
ORDDEF **names; /* array of entry point names (points into entry_points) */
ORDDEF **ordinals; /* array of dll ordinals (points into entry_points) */
@@ -297,6 +298,7 @@ extern void output_gnu_stack_note(void);
extern void add_import_dll( const char *name, const char *filename );
extern void add_delayed_import( const char *name );
extern void add_extra_ld_symbol( const char *name );
+extern void add_spec_extra_ld_symbol( const char *name );
extern void read_undef_symbols( DLLSPEC *spec, char **argv );
extern void resolve_imports( DLLSPEC *spec );
extern int is_undefined( const char *name );
Index: wine/tools/winebuild/main.c
===================================================================
--- wine.orig/tools/winebuild/main.c
+++ wine/tools/winebuild/main.c
@@ -396,8 +396,25 @@ static const char *get_default_entry_poi
{
if (spec->characteristics & IMAGE_FILE_DLL) return "DllMain";
if (spec->subsystem == IMAGE_SUBSYSTEM_NATIVE) return "DriverEntry";
- if (spec->type == SPEC_WIN16) return "__wine_spec_exe16_entry";
- return "__wine_spec_exe_entry";
+ if (spec->type == SPEC_WIN16) {
+ add_spec_extra_ld_symbol("WinMain16");
+ return "__wine_spec_exe16_entry";
+ }
+ if (spec->unicode_app) {
+ /* __wine_spec_exe_wentry always calls wmain */
+ add_spec_extra_ld_symbol("wmain");
+ if(spec->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
+ add_spec_extra_ld_symbol("wWinMain");
+ }
+ return "__wine_spec_exe_wentry";
+ } else {
+ /* __wine_spec_exe_entry always calls main */
+ add_spec_extra_ld_symbol("main");
+ if(spec->subsystem == IMAGE_SUBSYSTEM_WINDOWS_GUI) {
+ add_spec_extra_ld_symbol("WinMain");
+ }
+ return "__wine_spec_exe_entry";
+ }
}
/* parse options from the argv array and remove all the recognized ones */
@@ -448,6 +465,7 @@ static char **parse_options( int argc, c
else if (!strcmp( optarg, "thumb" )) thumb_mode = 1;
else if (!strcmp( optarg, "no-cygwin" )) use_msvcrt = 1;
else if (!strcmp( optarg, "unix" )) unix_lib = 1;
+ else if (!strcmp( optarg, "unicode" )) spec->unicode_app = 1;
else if (!strncmp( optarg, "cpu=", 4 )) cpu_option = xstrdup( optarg + 4 );
else if (!strncmp( optarg, "fpu=", 4 )) fpu_option = xstrdup( optarg + 4 );
else if (!strncmp( optarg, "arch=", 5 )) arch_option = xstrdup( optarg + 5 );
Index: wine/tools/winebuild/spec32.c
===================================================================
--- wine.orig/tools/winebuild/spec32.c
+++ wine/tools/winebuild/spec32.c
@@ -50,6 +50,13 @@ int needs_get_pc_thunk = 0;
static const char builtin_signature[32] = "Wine builtin DLL";
static const char fakedll_signature[32] = "Wine placeholder DLL";
+static struct strarray spec_extra_ld_symbols = { 0 }; /* list of extra symbols that ld should resolve */
+
+/* add a symbol to the list of extra symbols that ld must resolve */
+void add_spec_extra_ld_symbol( const char *name )
+{
+ strarray_add( &spec_extra_ld_symbols, name, NULL );
+}
/* check if entry point needs a relay thunk */
static inline int needs_relay( const ORDDEF *odp )
@@ -602,6 +609,7 @@ void output_exports( DLLSPEC *spec )
void output_module( DLLSPEC *spec )
{
int machine = 0;
+ int i;
unsigned int page_size = get_page_size();
const char *data_dirs[16] = { NULL };
@@ -680,6 +688,10 @@ void output_module( DLLSPEC *spec )
output( "\t.long 0\n" ); /* SizeOfCode */
output( "\t.long 0\n" ); /* SizeOfInitializedData */
output( "\t.long 0\n" ); /* SizeOfUninitializedData */
+
+ for (i = 0; i < spec_extra_ld_symbols.count; i++)
+ output( "\t.globl %s\n", asm_name(spec_extra_ld_symbols.str[i]) );
+
/* note: we expand the AddressOfEntryPoint field on 64-bit by overwriting the BaseOfCode field */
output( "\t%s %s\n", /* AddressOfEntryPoint */
get_asm_ptr_keyword(), spec->init_func ? asm_name(spec->init_func) : "0" );
Index: wine/tools/winegcc/winegcc.c
===================================================================
--- wine.orig/tools/winegcc/winegcc.c
+++ wine/tools/winegcc/winegcc.c
@@ -1228,8 +1228,6 @@ static void build(struct options* opts)
entry_point = (is_pe && opts->target_cpu == CPU_x86) ? "DriverEntry(a)8" : "DriverEntry";
else if (opts->use_msvcrt && !opts->shared && !opts->win16_app)
entry_point = opts->unicode_app ? "wmainCRTStartup" : "mainCRTStartup";
- else if (!is_pe && !opts->shared && opts->unicode_app)
- entry_point = "__wine_spec_exe_wentry";
}
else entry_point = opts->entry_point;
@@ -1241,6 +1239,8 @@ static void build(struct options* opts)
spec_o_name = get_temp_file(output_name, ".spec.o");
if (opts->force_pointer_size)
strarray_add(spec_args, strmake("-m%u", 8 * opts->force_pointer_size ));
+ if(opts->unicode_app)
+ strarray_add(spec_args, "-municode");
strarray_add(spec_args, "-D_REENTRANT");
if (opts->pic && !is_pe) strarray_add(spec_args, "-fPIC");
strarray_add(spec_args, opts->shared ? "--dll" : "--exe");
2
1
This allows a CMake toolchain (or other caller) to treat winegcc like MinGW,
specifying that it produce a separate file for imports, e.g.
set(CMAKE_IMPORT_LIBRARY_PREFIX lib)
set(CMAKE_IMPORT_LIBRARY_SUFFIX .a)
string(APPEND CMAKE_C_CREATE_SHARED_LIBRARY " -Wl,--out-implib,<TARGET_IMPLIB>")
Signed-off-by: Kevin Puetz <PuetzKevinA(a)JohnDeere.com>
---
makedep.c isn't changed to use use this because the few cases in which wine
currently uses #pragma implib (and thus winebuild --implib) involve
putting some (but not all) of the object files into the libfoo.a as well.
The motive is to fix our CMake toolchain for wineg++ to support using
target_link_libraries to link other SHARED_LIBRARY targets in the project.
This broke when wine-5.7 removed __wine_spec_init from winecrt0; the issue
is that CMake links to with an absolute path to the .so (i.e. foo.dll.so).
So we had been (unnnoticed until it quit working) getting an ELF DT_NEEDED
instead of a PE import. This "worked" before, since __wine_spec_init
would still register the builtin dll loaded in such a fashion. Now the
dependency's own dllimports (from kernel32, etc) don't get loaded anymore.
And I'm pretty sure it only worked before by happy accident.
CMake supports windows-style DLL/implib separation, but it really wants
the link rule to produce both artifacts (as MSVC/MinGW do) and the implib
needs to be a file that can be passed to linking as an absolute path.
And (for least surprise) it seems like that filename should work with -lfoo
too, even though CMake will always pass a full path. libfoo.def doesn't,
because winegcc sees libfoo.def as the spec_file (i.e. --export). The only
way I could find to pass a libfoo.def file and have it be imports (besides
having winegcc find it via -lfoo) was to conceal it in -Wb,libfoo.def,
which feels rather hacky.
Just forwarding the mingw-style -Wl,--out-implib to winebuild --implib
seemed easy and MinGW-like (which winegcc often seems to aim for).
add_undef_import is subtle, but it's already there (for #pragma implib)
so I didn't see any a reason to prefer a libfoo.def over a libfoo.a,
when the latter already works as a filename and as -lfoo.
If I've overlooked some reason it's preferable to use .def files, perhaps
there could be a distinct extension (.impdef, .a.def, or .lib ala MSVC?)
which get_file_type treats as file_dll and guess_lib_type (also?) searches.
Then --out-implib could check the extension and use winebuild --def
vs winebuild --implib accordingly (like how winegcc already reacts to the
extension of -o to decide between generate_app_loader, --fake, etc).
Signed-off-by in the sense that I think this is correct and adequate,
but I'm happy to take feedback if there's other use-cases an upstream
submission should try to address...
Index: wine/tools/winegcc/winegcc.c
===================================================================
--- wine.orig/tools/winegcc/winegcc.c
+++ wine/tools/winegcc/winegcc.c
@@ -231,6 +231,7 @@ struct options
const char* entry_point;
const char* prelink;
const char* debug_file;
+ const char* out_implib;
strarray* prefix;
strarray* lib_dirs;
strarray* args;
@@ -1085,7 +1086,7 @@ static void add_library( struct options
static void build(struct options* opts)
{
strarray *lib_dirs, *files;
- strarray *spec_args, *link_args, *tool;
+ strarray *spec_args, *link_args, *implib_args, *tool;
char *output_file, *output_path;
const char *spec_o_name, *libgcc = NULL;
const char *output_name, *spec_file, *lang;
@@ -1454,6 +1455,26 @@ static void build(struct options* opts)
strarray_free(tool);
}
+ if(opts->out_implib)
+ {
+ if (!spec_file)
+ error("--out-implib requires a .spec or .def file\n");
+
+ implib_args = get_winebuild_args( opts );
+ if ((tool = build_tool_name( opts, TOOL_CC ))) strarray_add( implib_args, strmake( "--cc-cmd=%s", strarray_tostring( tool, " " )));
+ if ((tool = build_tool_name( opts, TOOL_LD ))) strarray_add( implib_args, strmake( "--ld-cmd=%s", strarray_tostring( tool, " " )));
+
+ strarray_add(implib_args, "--implib");
+ strarray_add(implib_args, "-o");
+ strarray_add(implib_args, opts->out_implib);
+ strarray_add(implib_args, "--export");
+ strarray_add(implib_args, spec_file);
+ strarray_addall(implib_args, opts->winebuild_args);
+
+ spawn(opts->prefix, implib_args, 0);
+ strarray_free (implib_args);
+ }
+
/* set the base address with prelink if linker support is not present */
if (opts->prelink && !opts->target)
{
@@ -1966,6 +1987,11 @@ int main(int argc, char **argv)
strarray_add( opts.files, strmake( "-Wl,%s", Wl->base[j] ));
continue;
}
+ if (!strcmp(Wl->base[j], "--out-implib"))
+ {
+ opts.out_implib = strdup( Wl->base[++j] );
+ continue;
+ }
if (!strcmp(Wl->base[j], "-static")) linking = -1;
strarray_add(opts.linker_args, strmake("-Wl,%s",Wl->base[j]));
}
Index: wine/tools/winegcc/winegcc.man.in
===================================================================
--- wine.orig/tools/winegcc/winegcc.man.in
+++ wine/tools/winegcc/winegcc.man.in
@@ -72,6 +72,9 @@ Do not add the winecrt0 library when lin
.IP \fB-Wb,\fIoption\fR
Pass an option to winebuild. If \fIoption\fR contains
commas, it is split into multiple options at the commas.
+.IP "\fB-b,--target \fItarget\fR"
+.IP "\fB-Wl,--out-implib,\fIlib.a\fR"
+This option should be used while linking a dll, and is implemented for compatibility with MinGW-gcc. A \fIlib.spec\fR or \fIlib.def\fR must also be provided. Despite the name, it is actually forwarded to \fBwinebuild --implib -o \fIlib.a\fR rather than to the linker.
.SH ENVIRONMENT
.TP
.B WINEBUILD
1
0
[PATCH] mmdveapi: Support older version of the AudioClientProperties structure
by Andrew Eikum Nov. 20, 2020
by Andrew Eikum Nov. 20, 2020
Nov. 20, 2020
Warframe when using a win10 prefix uses an xaudio2_9redist.dll which
uses the older AudioClientProperties structure (missing the Options
member).
Based on a patch by Alistair Leslie-Hughes.
Signed-off-by: Andrew Eikum <aeikum(a)codeweavers.com>
---
dlls/mmdevapi/tests/render.c | 12 +++++++++++-
dlls/winealsa.drv/mmdevdrv.c | 22 +++++++++++++++-------
dlls/wineandroid.drv/mmdevdrv.c | 22 +++++++++++++++-------
dlls/winecoreaudio.drv/mmdevdrv.c | 22 +++++++++++++++-------
dlls/wineoss.drv/mmdevdrv.c | 22 +++++++++++++++-------
dlls/winepulse.drv/mmdevdrv.c | 22 +++++++++++++++-------
include/audioclient.idl | 8 ++++++++
7 files changed, 94 insertions(+), 36 deletions(-)
diff --git a/dlls/mmdevapi/tests/render.c b/dlls/mmdevapi/tests/render.c
index a0aa1b18936..495c1c6f496 100644
--- a/dlls/mmdevapi/tests/render.c
+++ b/dlls/mmdevapi/tests/render.c
@@ -276,6 +276,7 @@ static void test_audioclient(void)
hr = IAudioClient2_SetClientProperties(ac2, NULL);
ok(hr == E_POINTER, "SetClientProperties with NULL props gave wrong error: %08x\n", hr);
+ /* invalid cbSize */
client_props.cbSize = 0;
client_props.bIsOffload = FALSE;
client_props.eCategory = AudioCategory_BackgroundCapableMedia;
@@ -284,7 +285,8 @@ static void test_audioclient(void)
hr = IAudioClient2_SetClientProperties(ac2, &client_props);
ok(hr == E_INVALIDARG, "SetClientProperties with invalid cbSize gave wrong error: %08x\n", hr);
- client_props.cbSize = sizeof(client_props);
+ /* offload consistency */
+ client_props.cbSize = sizeof(client_props) - sizeof(client_props.Options);
client_props.bIsOffload = TRUE;
hr = IAudioClient2_SetClientProperties(ac2, &client_props);
@@ -293,10 +295,18 @@ static void test_audioclient(void)
else
ok(hr == S_OK, "SetClientProperties(offload) failed: %08x\n", hr);
+ /* disable offload */
client_props.bIsOffload = FALSE;
hr = IAudioClient2_SetClientProperties(ac2, &client_props);
ok(hr == S_OK, "SetClientProperties failed: %08x\n", hr);
+ /* Options field added in Win 8.1 */
+ client_props.cbSize = sizeof(client_props);
+ hr = IAudioClient2_SetClientProperties(ac2, &client_props);
+ ok(hr == S_OK ||
+ broken(hr == E_INVALIDARG) /* <= win8 */,
+ "SetClientProperties failed: %08x\n", hr);
+
IAudioClient2_Release(ac2);
}
else
diff --git a/dlls/winealsa.drv/mmdevdrv.c b/dlls/winealsa.drv/mmdevdrv.c
index 0c255a66f7d..318350471db 100644
--- a/dlls/winealsa.drv/mmdevdrv.c
+++ b/dlls/winealsa.drv/mmdevdrv.c
@@ -2676,21 +2676,29 @@ static HRESULT WINAPI AudioClient_SetClientProperties(IAudioClient3 *iface,
const AudioClientProperties *prop)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ const Win8AudioClientProperties *legacy_prop = (const Win8AudioClientProperties *)prop;
TRACE("(%p)->(%p)\n", This, prop);
- if(!prop)
+ if(!legacy_prop)
return E_POINTER;
- if(prop->cbSize != sizeof(*prop))
+ if(legacy_prop->cbSize == sizeof(AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory,
+ prop->Options);
+ }else if(legacy_prop->cbSize == sizeof(Win8AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory);
+ }else{
+ WARN("Unsupported Size = %d\n", legacy_prop->cbSize);
return E_INVALIDARG;
+ }
- TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
- prop->bIsOffload,
- prop->eCategory,
- prop->Options);
- if(prop->bIsOffload)
+ if(legacy_prop->bIsOffload)
return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE;
return S_OK;
diff --git a/dlls/wineandroid.drv/mmdevdrv.c b/dlls/wineandroid.drv/mmdevdrv.c
index 7d543ec4f61..d9b7cde2c80 100644
--- a/dlls/wineandroid.drv/mmdevdrv.c
+++ b/dlls/wineandroid.drv/mmdevdrv.c
@@ -1635,21 +1635,29 @@ static HRESULT WINAPI AudioClient_SetClientProperties(IAudioClient3 *iface,
const AudioClientProperties *prop)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ const Win8AudioClientProperties *legacy_prop = (const Win8AudioClientProperties *)prop;
TRACE("(%p)->(%p)\n", This, prop);
- if(!prop)
+ if(!legacy_prop)
return E_POINTER;
- if(prop->cbSize != sizeof(*prop))
+ if(legacy_prop->cbSize == sizeof(AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory,
+ prop->Options);
+ }else if(legacy_prop->cbSize == sizeof(Win8AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory);
+ }else{
+ WARN("Unsupported Size = %d\n", legacy_prop->cbSize);
return E_INVALIDARG;
+ }
- TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
- prop->bIsOffload,
- prop->eCategory,
- prop->Options);
- if(prop->bIsOffload)
+ if(legacy_prop->bIsOffload)
return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE;
return S_OK;
diff --git a/dlls/winecoreaudio.drv/mmdevdrv.c b/dlls/winecoreaudio.drv/mmdevdrv.c
index 846e0ae3b1e..b002189e199 100644
--- a/dlls/winecoreaudio.drv/mmdevdrv.c
+++ b/dlls/winecoreaudio.drv/mmdevdrv.c
@@ -2243,21 +2243,29 @@ static HRESULT WINAPI AudioClient_SetClientProperties(IAudioClient3 *iface,
const AudioClientProperties *prop)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ const Win8AudioClientProperties *legacy_prop = (const Win8AudioClientProperties *)prop;
TRACE("(%p)->(%p)\n", This, prop);
- if(!prop)
+ if(!legacy_prop)
return E_POINTER;
- if(prop->cbSize != sizeof(*prop))
+ if(legacy_prop->cbSize == sizeof(AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory,
+ prop->Options);
+ }else if(legacy_prop->cbSize == sizeof(Win8AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory);
+ }else{
+ WARN("Unsupported Size = %d\n", legacy_prop->cbSize);
return E_INVALIDARG;
+ }
- TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
- prop->bIsOffload,
- prop->eCategory,
- prop->Options);
- if(prop->bIsOffload)
+ if(legacy_prop->bIsOffload)
return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE;
return S_OK;
diff --git a/dlls/wineoss.drv/mmdevdrv.c b/dlls/wineoss.drv/mmdevdrv.c
index fd0784eb323..db2c6b23914 100644
--- a/dlls/wineoss.drv/mmdevdrv.c
+++ b/dlls/wineoss.drv/mmdevdrv.c
@@ -1800,21 +1800,29 @@ static HRESULT WINAPI AudioClient_SetClientProperties(IAudioClient3 *iface,
const AudioClientProperties *prop)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ const Win8AudioClientProperties *legacy_prop = (const Win8AudioClientProperties *)prop;
TRACE("(%p)->(%p)\n", This, prop);
- if(!prop)
+ if(!legacy_prop)
return E_POINTER;
- if(prop->cbSize != sizeof(*prop))
+ if(legacy_prop->cbSize == sizeof(AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory,
+ prop->Options);
+ }else if(legacy_prop->cbSize == sizeof(Win8AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory);
+ }else{
+ WARN("Unsupported Size = %d\n", legacy_prop->cbSize);
return E_INVALIDARG;
+ }
- TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
- prop->bIsOffload,
- prop->eCategory,
- prop->Options);
- if(prop->bIsOffload)
+ if(legacy_prop->bIsOffload)
return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE;
return S_OK;
diff --git a/dlls/winepulse.drv/mmdevdrv.c b/dlls/winepulse.drv/mmdevdrv.c
index cef8a2d4d5b..417067f0bf8 100644
--- a/dlls/winepulse.drv/mmdevdrv.c
+++ b/dlls/winepulse.drv/mmdevdrv.c
@@ -2248,21 +2248,29 @@ static HRESULT WINAPI AudioClient_SetClientProperties(IAudioClient3 *iface,
const AudioClientProperties *prop)
{
ACImpl *This = impl_from_IAudioClient3(iface);
+ const Win8AudioClientProperties *legacy_prop = (const Win8AudioClientProperties *)prop;
TRACE("(%p)->(%p)\n", This, prop);
- if(!prop)
+ if(!legacy_prop)
return E_POINTER;
- if(prop->cbSize != sizeof(*prop))
+ if(legacy_prop->cbSize == sizeof(AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory,
+ prop->Options);
+ }else if(legacy_prop->cbSize == sizeof(Win8AudioClientProperties)){
+ TRACE("{ bIsOffload: %u, eCategory: 0x%x }\n",
+ legacy_prop->bIsOffload,
+ legacy_prop->eCategory);
+ }else{
+ WARN("Unsupported Size = %d\n", legacy_prop->cbSize);
return E_INVALIDARG;
+ }
- TRACE("{ bIsOffload: %u, eCategory: 0x%x, Options: 0x%x }\n",
- prop->bIsOffload,
- prop->eCategory,
- prop->Options);
- if(prop->bIsOffload)
+ if(legacy_prop->bIsOffload)
return AUDCLNT_E_ENDPOINT_OFFLOAD_NOT_CAPABLE;
return S_OK;
diff --git a/include/audioclient.idl b/include/audioclient.idl
index 132e78a602b..cd13be5d575 100644
--- a/include/audioclient.idl
+++ b/include/audioclient.idl
@@ -126,6 +126,14 @@ typedef struct _AudioClientProperties
AUDCLNT_STREAMOPTIONS Options;
} AudioClientProperties;
+typedef struct _Win8AudioClientProperties
+{
+ UINT32 cbSize;
+ BOOL bIsOffload;
+ AUDIO_STREAM_CATEGORY eCategory;
+ /* Options field added in Win 8.1 */
+} Win8AudioClientProperties;
+
[
local,
pointer_default(unique),
--
2.29.2
2
1