ReactOS.org
Sign In
Sign Up
Sign In
Sign Up
Manage this list
×
Keyboard Shortcuts
Thread View
j
: Next unread message
k
: Previous unread message
j a
: Jump to all threads
j l
: Jump to MailingList overview
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
List overview
Download
Ros-diffs
January 2018
----- 2024 -----
December 2024
November 2024
October 2024
September 2024
August 2024
July 2024
June 2024
May 2024
April 2024
March 2024
February 2024
January 2024
----- 2023 -----
December 2023
November 2023
October 2023
September 2023
August 2023
July 2023
June 2023
May 2023
April 2023
March 2023
February 2023
January 2023
----- 2022 -----
December 2022
November 2022
October 2022
September 2022
August 2022
July 2022
June 2022
May 2022
April 2022
March 2022
February 2022
January 2022
----- 2021 -----
December 2021
November 2021
October 2021
September 2021
August 2021
July 2021
June 2021
May 2021
April 2021
March 2021
February 2021
January 2021
----- 2020 -----
December 2020
November 2020
October 2020
September 2020
August 2020
July 2020
June 2020
May 2020
April 2020
March 2020
February 2020
January 2020
----- 2019 -----
December 2019
November 2019
October 2019
September 2019
August 2019
July 2019
June 2019
May 2019
April 2019
March 2019
February 2019
January 2019
----- 2018 -----
December 2018
November 2018
October 2018
September 2018
August 2018
July 2018
June 2018
May 2018
April 2018
March 2018
February 2018
January 2018
----- 2017 -----
December 2017
November 2017
October 2017
September 2017
August 2017
July 2017
June 2017
May 2017
April 2017
March 2017
February 2017
January 2017
----- 2016 -----
December 2016
November 2016
October 2016
September 2016
August 2016
July 2016
June 2016
May 2016
April 2016
March 2016
February 2016
January 2016
----- 2015 -----
December 2015
November 2015
October 2015
September 2015
August 2015
July 2015
June 2015
May 2015
April 2015
March 2015
February 2015
January 2015
----- 2014 -----
December 2014
November 2014
October 2014
September 2014
August 2014
July 2014
June 2014
May 2014
April 2014
March 2014
February 2014
January 2014
----- 2013 -----
December 2013
November 2013
October 2013
September 2013
August 2013
July 2013
June 2013
May 2013
April 2013
March 2013
February 2013
January 2013
----- 2012 -----
December 2012
November 2012
October 2012
September 2012
August 2012
July 2012
June 2012
May 2012
April 2012
March 2012
February 2012
January 2012
----- 2011 -----
December 2011
November 2011
October 2011
September 2011
August 2011
July 2011
June 2011
May 2011
April 2011
March 2011
February 2011
January 2011
----- 2010 -----
December 2010
November 2010
October 2010
September 2010
August 2010
July 2010
June 2010
May 2010
April 2010
March 2010
February 2010
January 2010
----- 2009 -----
December 2009
November 2009
October 2009
September 2009
August 2009
July 2009
June 2009
May 2009
April 2009
March 2009
February 2009
January 2009
----- 2008 -----
December 2008
November 2008
October 2008
September 2008
August 2008
July 2008
June 2008
May 2008
April 2008
March 2008
February 2008
January 2008
----- 2007 -----
December 2007
November 2007
October 2007
September 2007
August 2007
July 2007
June 2007
May 2007
April 2007
March 2007
February 2007
January 2007
----- 2006 -----
December 2006
November 2006
October 2006
September 2006
August 2006
July 2006
June 2006
May 2006
April 2006
March 2006
February 2006
January 2006
----- 2005 -----
December 2005
November 2005
October 2005
September 2005
August 2005
July 2005
June 2005
May 2005
April 2005
March 2005
February 2005
January 2005
----- 2004 -----
December 2004
November 2004
October 2004
September 2004
August 2004
July 2004
June 2004
May 2004
April 2004
March 2004
February 2004
ros-diffs@reactos.org
37 participants
372 discussions
Start a n
N
ew thread
01/01: [USP10] Re-use script caches for the same font. CORE-14192
by Thomas Faber
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=cd992d022ff8b6151a592…
commit cd992d022ff8b6151a59214ca0883d8f04bd4569 Author: Thomas Faber <thomas.faber(a)reactos.org> AuthorDate: Sat Jan 20 13:41:14 2018 +0100 Commit: Thomas Faber <thomas.faber(a)reactos.org> CommitDate: Sat Jan 20 15:55:07 2018 +0100 [USP10] Re-use script caches for the same font. CORE-14192 This significantly speeds up WM_SETTEXT in multiline edit controls. --- dll/win32/usp10/usp10.c | 69 ++++++++++++++++-- dll/win32/usp10/usp10_internal.h | 3 + modules/rostests/winetests/usp10/usp10.c | 118 +++++++++++++++++++++++++++++++ 3 files changed, 184 insertions(+), 6 deletions(-) diff --git a/dll/win32/usp10/usp10.c b/dll/win32/usp10/usp10.c index 058fc6f368..abc40fc891 100644 --- a/dll/win32/usp10/usp10.c +++ b/dll/win32/usp10/usp10.c @@ -664,6 +664,16 @@ static const SCRIPT_PROPERTIES *script_props[] = &scriptInformation[80].props, &scriptInformation[81].props }; +static CRITICAL_SECTION cs_script_cache; +static CRITICAL_SECTION_DEBUG cs_script_cache_dbg = +{ + 0, 0, &cs_script_cache, + { &cs_script_cache_dbg.ProcessLocksList, &cs_script_cache_dbg.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": script_cache") } +}; +static CRITICAL_SECTION cs_script_cache = { &cs_script_cache_dbg, -1, 0, 0, 0, 0 }; +static struct list script_cache_list = LIST_INIT(script_cache_list); + typedef struct { ScriptCache *sc; int numGlyphs; @@ -842,12 +852,34 @@ static inline BOOL set_cache_glyph_widths(SCRIPT_CACHE *psc, WORD glyph, ABC *ab static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc) { ScriptCache *sc; - int size; + unsigned size; + LOGFONTW lf; if (!psc) return E_INVALIDARG; if (*psc) return S_OK; if (!hdc) return E_PENDING; + if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(lf), &lf)) + { + return E_INVALIDARG; + } + /* Ensure canonical result by zeroing extra space in lfFaceName */ + size = strlenW(lf.lfFaceName); + memset(lf.lfFaceName + size, 0, sizeof(lf.lfFaceName) - size * sizeof(WCHAR)); + + EnterCriticalSection(&cs_script_cache); + LIST_FOR_EACH_ENTRY(sc, &script_cache_list, ScriptCache, entry) + { + if (!memcmp(&sc->lf, &lf, sizeof(lf))) + { + sc->refcount++; + LeaveCriticalSection(&cs_script_cache); + *psc = sc; + return S_OK; + } + } + LeaveCriticalSection(&cs_script_cache); + if (!(sc = heap_alloc_zero(sizeof(ScriptCache)))) return E_OUTOFMEMORY; if (!GetTextMetricsW(hdc, &sc->tm)) { @@ -861,18 +893,32 @@ static HRESULT init_script_cache(const HDC hdc, SCRIPT_CACHE *psc) sc->otm->otmSize = size; GetOutlineTextMetricsW(hdc, size, sc->otm); } - if (!GetObjectW(GetCurrentObject(hdc, OBJ_FONT), sizeof(LOGFONTW), &sc->lf)) - { - heap_free(sc); - return E_INVALIDARG; - } sc->sfnt = (GetFontData(hdc, MS_MAKE_TAG('h','e','a','d'), 0, NULL, 0)!=GDI_ERROR); if (!set_cache_font_properties(hdc, sc)) { heap_free(sc); return E_INVALIDARG; } + sc->lf = lf; + sc->refcount = 1; *psc = sc; + + EnterCriticalSection(&cs_script_cache); + list_add_head(&script_cache_list, &sc->entry); + LIST_FOR_EACH_ENTRY(sc, &script_cache_list, ScriptCache, entry) + { + if (sc != *psc && !memcmp(&sc->lf, &lf, sizeof(lf))) + { + /* Another thread won the race. Use their cache instead of ours */ + list_remove(&sc->entry); + sc->refcount++; + LeaveCriticalSection(&cs_script_cache); + heap_free(*psc); + *psc = sc; + return S_OK; + } + } + LeaveCriticalSection(&cs_script_cache); TRACE("<- %p\n", sc); return S_OK; } @@ -1025,6 +1071,17 @@ HRESULT WINAPI ScriptFreeCache(SCRIPT_CACHE *psc) { unsigned int i; INT n; + + EnterCriticalSection(&cs_script_cache); + if (--((ScriptCache *)*psc)->refcount > 0) + { + LeaveCriticalSection(&cs_script_cache); + *psc = NULL; + return S_OK; + } + list_remove(&((ScriptCache *)*psc)->entry); + LeaveCriticalSection(&cs_script_cache); + for (i = 0; i < GLYPH_MAX / GLYPH_BLOCK_SIZE; i++) { heap_free(((ScriptCache *)*psc)->widths[i]); diff --git a/dll/win32/usp10/usp10_internal.h b/dll/win32/usp10/usp10_internal.h index da5f3fe8eb..c0e28d542c 100644 --- a/dll/win32/usp10/usp10_internal.h +++ b/dll/win32/usp10/usp10_internal.h @@ -37,6 +37,7 @@ #include <wine/debug.h> #include <wine/unicode.h> +#include <wine/list.h> #define MS_MAKE_TAG( _x1, _x2, _x3, _x4 ) \ ( ( (ULONG)_x4 << 24 ) | \ @@ -194,6 +195,8 @@ typedef struct { } CacheGlyphPage; typedef struct { + struct list entry; + DWORD refcount; LOGFONTW lf; TEXTMETRICW tm; OUTLINETEXTMETRICW *otm; diff --git a/modules/rostests/winetests/usp10/usp10.c b/modules/rostests/winetests/usp10/usp10.c index 417d0b8888..1ea873786a 100644 --- a/modules/rostests/winetests/usp10/usp10.c +++ b/modules/rostests/winetests/usp10/usp10.c @@ -1836,6 +1836,7 @@ static void test_ScriptShape(HDC hdc) static const WCHAR test3[] = {0x30b7}; HRESULT hr; SCRIPT_CACHE sc = NULL; + SCRIPT_CACHE sc2 = NULL; WORD glyphs[4], glyphs2[4], logclust[4], glyphs3[4]; SCRIPT_VISATTR attrs[4]; SCRIPT_ITEM items[4]; @@ -1865,6 +1866,10 @@ static void test_ScriptShape(HDC hdc) ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); + hr = ScriptShape(hdc, &sc2, test1, 4, 4, &items[0].a, glyphs, logclust, attrs, &nb); + ok(hr == S_OK, "ScriptShape should return S_OK not %08x\n", hr); + ok(sc2 == sc, "caches %p, %p not identical\n", sc, sc2); + ScriptFreeCache(&sc2); memset(glyphs,-1,sizeof(glyphs)); memset(logclust,-1,sizeof(logclust)); @@ -2090,6 +2095,7 @@ static void test_ScriptPlace(HDC hdc) BOOL ret; HRESULT hr; SCRIPT_CACHE sc = NULL; + SCRIPT_CACHE sc2 = NULL; WORD glyphs[4], logclust[4]; SCRIPT_VISATTR attrs[4]; SCRIPT_ITEM items[2]; @@ -2127,6 +2133,11 @@ static void test_ScriptPlace(HDC hdc) ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr); ok(items[0].a.fNoGlyphIndex == FALSE, "fNoGlyphIndex TRUE\n"); + hr = ScriptPlace(hdc, &sc2, glyphs, 4, attrs, &items[0].a, widths, offset, NULL); + ok(hr == S_OK, "ScriptPlace should return S_OK not %08x\n", hr); + ok(sc2 == sc, "caches %p, %p not identical\n", sc, sc2); + ScriptFreeCache(&sc2); + if (widths[0] != 0) { int old_width = widths[0]; @@ -4112,6 +4123,112 @@ static void test_ScriptString_pSize(HDC hdc) ok(hr == S_OK, "Failed to free ssa, hr %#x.\n", hr); } +static void test_script_cache_reuse(void) +{ + HRESULT hr; + HWND hwnd1, hwnd2; + HDC hdc1, hdc2; + LOGFONTA lf; + HFONT hfont1, hfont2; + HFONT prev_hfont1, prev_hfont2; + SCRIPT_CACHE sc = NULL; + SCRIPT_CACHE sc2; + LONG height; + + hwnd1 = create_test_window(); + hwnd2 = create_test_window(); + + hdc1 = GetDC(hwnd1); + hdc2 = GetDC(hwnd2); + ok(hdc1 != NULL && hdc2 != NULL, "Failed to get window dc.\n"); + + memset(&lf, 0, sizeof(LOGFONTA)); + lstrcpyA(lf.lfFaceName, "Tahoma"); + + lf.lfHeight = 10; + hfont1 = CreateFontIndirectA(&lf); + ok(hfont1 != NULL, "CreateFontIndirectA failed\n"); + hfont2 = CreateFontIndirectA(&lf); + ok(hfont2 != NULL, "CreateFontIndirectA failed\n"); + ok(hfont1 != hfont2, "Expected fonts %p and %p to differ\n", hfont1, hfont2); + + prev_hfont1 = SelectObject(hdc1, hfont1); + ok(prev_hfont1 != NULL, "SelectObject failed: %p\n", prev_hfont1); + prev_hfont2 = SelectObject(hdc2, hfont1); + ok(prev_hfont2 != NULL, "SelectObject failed: %p\n", prev_hfont2); + + /* Get a script cache */ + hr = ScriptCacheGetHeight(hdc1, &sc, &height); + ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); + ok(sc != NULL, "Script cache is NULL\n"); + + /* Same font, same DC -> same SCRIPT_CACHE */ + sc2 = NULL; + hr = ScriptCacheGetHeight(hdc1, &sc2, &height); + ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); + ok(sc2 != NULL, "Script cache is NULL\n"); + ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2); + ScriptFreeCache(&sc2); + + /* Same font in different DC -> same SCRIPT_CACHE */ + sc2 = NULL; + hr = ScriptCacheGetHeight(hdc2, &sc2, &height); + ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); + ok(sc2 != NULL, "Script cache is NULL\n"); + ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2); + ScriptFreeCache(&sc2); + + /* Same font face & size, but different font handle */ + ok(SelectObject(hdc1, hfont2) != NULL, "SelectObject failed\n"); + ok(SelectObject(hdc2, hfont2) != NULL, "SelectObject failed\n"); + + sc2 = NULL; + hr = ScriptCacheGetHeight(hdc1, &sc2, &height); + ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); + ok(sc2 != NULL, "Script cache is NULL\n"); + ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2); + ScriptFreeCache(&sc2); + + sc2 = NULL; + hr = ScriptCacheGetHeight(hdc2, &sc2, &height); + ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); + ok(sc2 != NULL, "Script cache is NULL\n"); + ok(sc == sc2, "Expected caches %p, %p to be identical\n", sc, sc2); + ScriptFreeCache(&sc2); + + /* Different font size -- now we get a different SCRIPT_CACHE */ + SelectObject(hdc1, prev_hfont1); + SelectObject(hdc2, prev_hfont2); + DeleteObject(hfont2); + lf.lfHeight = 20; + hfont2 = CreateFontIndirectA(&lf); + ok(hfont2 != NULL, "CreateFontIndirectA failed\n"); + ok(SelectObject(hdc1, hfont2) != NULL, "SelectObject failed\n"); + ok(SelectObject(hdc2, hfont2) != NULL, "SelectObject failed\n"); + + sc2 = NULL; + hr = ScriptCacheGetHeight(hdc1, &sc2, &height); + ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); + ok(sc2 != NULL, "Script cache is NULL\n"); + ok(sc != sc2, "Expected caches %p, %p to be different\n", sc, sc2); + ScriptFreeCache(&sc2); + + sc2 = NULL; + hr = ScriptCacheGetHeight(hdc2, &sc2, &height); + ok(hr == S_OK, "expected S_OK, got 0x%08x\n", hr); + ok(sc2 != NULL, "Script cache is NULL\n"); + ok(sc != sc2, "Expected caches %p, %p to be different\n", sc, sc2); + ScriptFreeCache(&sc2); + + ScriptFreeCache(&sc); + SelectObject(hdc1, prev_hfont1); + SelectObject(hdc2, prev_hfont2); + DeleteObject(hfont1); + DeleteObject(hfont2); + DestroyWindow(hwnd1); + DestroyWindow(hwnd2); +} + static void init_tests(void) { HMODULE module = GetModuleHandleA("usp10.dll"); @@ -4185,6 +4302,7 @@ START_TEST(usp10) test_ScriptGetLogicalWidths(); test_ScriptIsComplex(); + test_script_cache_reuse(); ReleaseDC(hwnd, hdc); DestroyWindow(hwnd);
6 years, 11 months
1
0
0
0
01/01: [CMAKE/WIDL] Add rudimentary dependency tracking in add_rpcproxy_files CORE-14204
by Mark Jansen
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=7e9fb41b9f6bf9a677651…
commit 7e9fb41b9f6bf9a677651f080853d5f4f50b52e3 Author: Mark Jansen <mark.jansen(a)reactos.org> AuthorDate: Mon Jan 15 21:04:56 2018 +0100 Commit: Mark Jansen <mark.jansen(a)reactos.org> CommitDate: Sat Jan 20 15:46:25 2018 +0100 [CMAKE/WIDL] Add rudimentary dependency tracking in add_rpcproxy_files CORE-14204 --- sdk/cmake/widl-support.cmake | 21 ++++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/sdk/cmake/widl-support.cmake b/sdk/cmake/widl-support.cmake index 30c4c0b966..267459383b 100644 --- a/sdk/cmake/widl-support.cmake +++ b/sdk/cmake/widl-support.cmake @@ -45,11 +45,22 @@ function(add_rpcproxy_files) foreach(FILE ${ARGN}) get_filename_component(NAME ${FILE} NAME_WE) - list(APPEND IDLS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}) - add_custom_command( - OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.h - COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -p -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c -h -H ${NAME}_p.h ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} - DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} native-widl) + # Most proxy idl's have names like <proxyname>_<original>.idl + # We use this to create a dependency from the proxy to the original idl + string(REPLACE "_" ";" SPLIT_FILE ${FILE}) + list(LENGTH SPLIT_FILE len) + unset(EXTRA_DEP) + if(len STREQUAL "2") + list(GET SPLIT_FILE 1 SPLIT_FILE) + if(EXISTS "${REACTOS_SOURCE_DIR}/sdk/include/psdk/${SPLIT_FILE}") + set(EXTRA_DEP ${REACTOS_SOURCE_DIR}/sdk/include/psdk/${SPLIT_FILE}) + endif() + endif() + list(APPEND IDLS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE}) + add_custom_command( + OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.h + COMMAND native-widl ${INCLUDES} ${DEFINES} ${IDL_FLAGS} -p -o ${CMAKE_CURRENT_BINARY_DIR}/${NAME}_p.c -h -H ${NAME}_p.h ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} + DEPENDS ${CMAKE_CURRENT_SOURCE_DIR}/${FILE} ${EXTRA_DEP} native-widl) endforeach() # Extra pass to generate dlldata
6 years, 11 months
1
0
0
0
01/01: [NFI] Remove the $Extend specific case. This fixes a FIXME
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a34d807311c1e5d8c73d1…
commit a34d807311c1e5d8c73d1156d0e545667b327e23 Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Sat Jan 20 15:35:05 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Sat Jan 20 15:35:05 2018 +0100 [NFI] Remove the $Extend specific case. This fixes a FIXME --- .../rosapps/applications/rosinternals/nfi/nfi.c | 57 +++++++++++----------- 1 file changed, 28 insertions(+), 29 deletions(-) diff --git a/modules/rosapps/applications/rosinternals/nfi/nfi.c b/modules/rosapps/applications/rosinternals/nfi/nfi.c index b7b28792b6..3aa54a6d6b 100644 --- a/modules/rosapps/applications/rosinternals/nfi/nfi.c +++ b/modules/rosapps/applications/rosinternals/nfi/nfi.c @@ -164,6 +164,26 @@ void PrintUsage(void) /* FIXME */ } +void AddToCache(PWSTR Name, DWORD Length, ULONGLONG MftId) +{ + PNAME_CACHE_ENTRY CacheEntry; + + /* Allocate an entry big enough to store name and cache info */ + CacheEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(NAME_CACHE_ENTRY) + Length); + if (CacheEntry == NULL) + { + return; + } + + /* Insert in head (likely more perf) */ + CacheEntry->Next = CacheHead; + CacheHead = CacheEntry; + /* Set up entry with full path */ + CacheEntry->MftId = MftId; + CacheEntry->NameLen = Length; + CopyMemory(CacheEntry->Name, Name, Length); +} + void PrintPrettyName(PNTFS_ATTR_RECORD Attributes, PNTFS_ATTR_RECORD AttributesEnd, ULONGLONG MftId) { BOOLEAN FirstRun, Found; @@ -176,6 +196,13 @@ void PrintPrettyName(PNTFS_ATTR_RECORD Attributes, PNTFS_ATTR_RECORD AttributesE if (MftId <= NTFS_FILE_EXTEND) { _tprintf(_T("%s\n"), KnownEntries[MftId]); + + /* $Extend can contain entries, add it in cache */ + if (MftId == NTFS_FILE_EXTEND) + { + AddToCache(L"\\$Extend", sizeof(L"\\$Extend") - sizeof(UNICODE_NULL), NTFS_FILE_EXTEND); + } + return; } @@ -221,21 +248,6 @@ TryAgain: Length = Name->NameLength + 1; Display[Length] = UNICODE_NULL; } - /* Specific case for $Extend\ files - * FIXME: Should be made more generic? - */ - else if (ParentId == NTFS_FILE_EXTEND) - { - Display[0] = L'\\'; - Length = wcslen(L"$Extend"); - CopyMemory(&Display[1], L"$Extend", Length * sizeof(WCHAR)); - ++Length; - Display[Length] = L'\\'; - ++Length; - CopyMemory(Display + Length, Name->Name, Name->NameLength * sizeof(WCHAR)); - Length += Name->NameLength; - Display[Length] = UNICODE_NULL; - } /* Default case */ else { @@ -279,20 +291,7 @@ TryAgain: /* If that's a directory, put it in the cache */ if (Name->FileAttributes & NTFS_FILE_TYPE_DIRECTORY) { - PNAME_CACHE_ENTRY CacheEntry; - - /* Allocate an entry big enough to store name and cache info */ - CacheEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(NAME_CACHE_ENTRY) + Length * sizeof(WCHAR)); - if (CacheEntry != NULL) - { - /* Insert in head (likely more perf) */ - CacheEntry->Next = CacheHead; - CacheHead = CacheEntry; - /* Set up entry with full path */ - CacheEntry->MftId = MftId; - CacheEntry->NameLen = Length * sizeof(WCHAR); - CopyMemory(CacheEntry->Name, Display, Length * sizeof(WCHAR)); - } + AddToCache(Display, Length * sizeof(WCHAR), MftId); } /* Now, just quit */
6 years, 11 months
1
0
0
0
01/01: [NFI] Add a first skeleton of what NFI could be.
by Pierre Schweitzer
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a46d9999dd96d9a036924…
commit a46d9999dd96d9a036924712d4eae80d06c8ebcd Author: Pierre Schweitzer <pierre(a)reactos.org> AuthorDate: Sat Jan 20 14:52:39 2018 +0100 Commit: Pierre Schweitzer <pierre(a)reactos.org> CommitDate: Sat Jan 20 14:54:00 2018 +0100 [NFI] Add a first skeleton of what NFI could be. All it will do for now is dumping the MFT / Files and their attributes. It lacks many features, could be really improved and is bugged. Note that logical sectors dump seems to be broken. MS NFI and this one don't agree on values. Developed against W2K3. --- .../applications/rosinternals/CMakeLists.txt | 1 + .../applications/rosinternals/nfi/CMakeLists.txt | 5 + .../rosapps/applications/rosinternals/nfi/nfi.c | 589 +++++++++++++++++++++ .../rosapps/applications/rosinternals/nfi/nfi.rc | 4 + 4 files changed, 599 insertions(+) diff --git a/modules/rosapps/applications/rosinternals/CMakeLists.txt b/modules/rosapps/applications/rosinternals/CMakeLists.txt index 1932f92bf5..298b745d09 100644 --- a/modules/rosapps/applications/rosinternals/CMakeLists.txt +++ b/modules/rosapps/applications/rosinternals/CMakeLists.txt @@ -1,3 +1,4 @@ add_subdirectory(movefile) +add_subdirectory(nfi) add_subdirectory(ntfsinfo) add_subdirectory(pendmoves) diff --git a/modules/rosapps/applications/rosinternals/nfi/CMakeLists.txt b/modules/rosapps/applications/rosinternals/nfi/CMakeLists.txt new file mode 100644 index 0000000000..9fa5aec5dd --- /dev/null +++ b/modules/rosapps/applications/rosinternals/nfi/CMakeLists.txt @@ -0,0 +1,5 @@ +list(APPEND SOURCE nfi.c nfi.rc) +add_executable(nfi ${SOURCE}) +set_module_type(nfi win32cui UNICODE) +add_importlibs(nfi msvcrt kernel32 ntdll) +add_cd_file(TARGET nfi DESTINATION reactos/system32 FOR all) diff --git a/modules/rosapps/applications/rosinternals/nfi/nfi.c b/modules/rosapps/applications/rosinternals/nfi/nfi.c new file mode 100644 index 0000000000..b7b28792b6 --- /dev/null +++ b/modules/rosapps/applications/rosinternals/nfi/nfi.c @@ -0,0 +1,589 @@ +/* + * COPYRIGHT: See COPYING in the top level directory + * PROJECT: ReactOS NTFS Information tool + * FILE: rosinternals/nfi/nfi.c + * PURPOSE: Query information from NTFS volume using FSCTL + * PROGRAMMERS: Pierre Schweitzer <pierre(a)reactos.org> + */ + +#include <windows.h> +#include <tchar.h> +#include <stdio.h> + +typedef struct +{ + ULONG Type; + USHORT UsaOffset; + USHORT UsaCount; + ULONGLONG Lsn; +} NTFS_RECORD_HEADER, *PNTFS_RECORD_HEADER; + +#define NRH_FILE_TYPE 0x454C4946 + +typedef enum +{ + AttributeStandardInformation = 0x10, + AttributeAttributeList = 0x20, + AttributeFileName = 0x30, + AttributeObjectId = 0x40, + AttributeSecurityDescriptor = 0x50, + AttributeVolumeName = 0x60, + AttributeVolumeInformation = 0x70, + AttributeData = 0x80, + AttributeIndexRoot = 0x90, + AttributeIndexAllocation = 0xA0, + AttributeBitmap = 0xB0, + AttributeReparsePoint = 0xC0, + AttributeEAInformation = 0xD0, + AttributeEA = 0xE0, + AttributePropertySet = 0xF0, + AttributeLoggedUtilityStream = 0x100, + AttributeEnd = 0xFFFFFFFF +} ATTRIBUTE_TYPE, *PATTRIBUTE_TYPE; + +typedef struct _FILE_RECORD_HEADER +{ + NTFS_RECORD_HEADER Ntfs; + USHORT SequenceNumber; + USHORT LinkCount; + USHORT AttributeOffset; + USHORT Flags; + ULONG BytesInUse; + ULONG BytesAllocated; + ULONGLONG BaseFileRecord; + USHORT NextAttributeNumber; +} FILE_RECORD_HEADER, *PFILE_RECORD_HEADER; + +typedef struct +{ + ULONG Type; + ULONG Length; + UCHAR IsNonResident; + UCHAR NameLength; + USHORT NameOffset; + USHORT Flags; + USHORT Instance; + union + { + struct + { + ULONG ValueLength; + USHORT ValueOffset; + UCHAR Flags; + UCHAR Reserved; + } Resident; + struct + { + ULONGLONG LowestVCN; + ULONGLONG HighestVCN; + USHORT MappingPairsOffset; + USHORT CompressionUnit; + UCHAR Reserved[4]; + LONGLONG AllocatedSize; + LONGLONG DataSize; + LONGLONG InitializedSize; + LONGLONG CompressedSize; + } NonResident; + }; +} NTFS_ATTR_RECORD, *PNTFS_ATTR_RECORD; + +typedef struct +{ + ULONGLONG DirectoryFileReferenceNumber; + ULONGLONG CreationTime; + ULONGLONG ChangeTime; + ULONGLONG LastWriteTime; + ULONGLONG LastAccessTime; + ULONGLONG AllocatedSize; + ULONGLONG DataSize; + ULONG FileAttributes; + union + { + struct + { + USHORT PackedEaSize; + USHORT AlignmentOrReserved; + } EaInfo; + ULONG ReparseTag; + } Extended; + UCHAR NameLength; + UCHAR NameType; + WCHAR Name[1]; +} FILENAME_ATTRIBUTE, *PFILENAME_ATTRIBUTE; + +#define NTFS_FILE_NAME_POSIX 0 +#define NTFS_FILE_NAME_WIN32 1 +#define NTFS_FILE_NAME_DOS 2 +#define NTFS_FILE_NAME_WIN32_AND_DOS 3 + +#define NTFS_FILE_MFT 0 +#define NTFS_FILE_MFTMIRR 1 +#define NTFS_FILE_LOGFILE 2 +#define NTFS_FILE_VOLUME 3 +#define NTFS_FILE_ATTRDEF 4 +#define NTFS_FILE_ROOT 5 +#define NTFS_FILE_BITMAP 6 +#define NTFS_FILE_BOOT 7 +#define NTFS_FILE_BADCLUS 8 +#define NTFS_FILE_QUOTA 9 +#define NTFS_FILE_UPCASE 10 +#define NTFS_FILE_EXTEND 11 + +PWSTR KnownEntries[NTFS_FILE_EXTEND + 1] = +{ + _T("Master File Table ($Mft)"), + _T("Master File Table Mirror ($MftMirr)"), + _T("Log File ($LogFile)"), + _T("DASD ($Volume)"), + _T("Attribute Definition Table ($AttrDef)"), + _T("Root Directory"), + _T("Volume Bitmap ($BitMap)"), + _T("Boot Sectors ($Boot)"), + _T("Bad Cluster List ($BadClus)"), + _T("Security ($Secure)"), + _T("Upcase Table ($UpCase)"), + _T("Extend Table ($Extend)") +}; + +#define NTFS_MFT_MASK 0x0000FFFFFFFFFFFFULL + +#define NTFS_FILE_TYPE_DIRECTORY 0x10000000 + +typedef struct _NAME_CACHE_ENTRY +{ + struct _NAME_CACHE_ENTRY * Next; + ULONGLONG MftId; + ULONG NameLen; + WCHAR Name[1]; +} NAME_CACHE_ENTRY, *PNAME_CACHE_ENTRY; + +PNAME_CACHE_ENTRY CacheHead = NULL; + +void PrintUsage(void) +{ + /* FIXME */ +} + +void PrintPrettyName(PNTFS_ATTR_RECORD Attributes, PNTFS_ATTR_RECORD AttributesEnd, ULONGLONG MftId) +{ + BOOLEAN FirstRun, Found; + PNTFS_ATTR_RECORD Attribute; + + FirstRun = TRUE; + Found = FALSE; + + /* Setup name for "standard" files */ + if (MftId <= NTFS_FILE_EXTEND) + { + _tprintf(_T("%s\n"), KnownEntries[MftId]); + return; + } + + /* We'll first try to use the Win32 name + * If we fail finding it, we'll loop again for any other name + */ +TryAgain: + /* Loop all the attributes */ + Attribute = Attributes; + while (Attribute < AttributesEnd && Attribute->Type != AttributeEnd) + { + WCHAR Display[MAX_PATH]; + PFILENAME_ATTRIBUTE Name; + ULONGLONG ParentId; + ULONG Length; + + /* Move to the next arg if: + * - Not a file name + * - Not resident (should never happen!) + */ + if (Attribute->Type != AttributeFileName || Attribute->IsNonResident) + { + Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + continue; + } + + /* Get the attribute data */ + Name = (PFILENAME_ATTRIBUTE)((ULONG_PTR)Attribute + Attribute->Resident.ValueOffset); + /* If not Win32, only accept if it wasn't the first run */ + if ((Name->NameType == NTFS_FILE_NAME_POSIX || Name->NameType == NTFS_FILE_NAME_DOS) && FirstRun) + { + Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + continue; + } + + /* We accepted that name, get the parent ID to setup name */ + ParentId = Name->DirectoryFileReferenceNumber & NTFS_MFT_MASK; + /* If root, easy, just print \ */ + if (ParentId == NTFS_FILE_ROOT) + { + Display[0] = L'\\'; + CopyMemory(&Display[1], Name->Name, Name->NameLength * sizeof(WCHAR)); + Length = Name->NameLength + 1; + Display[Length] = UNICODE_NULL; + } + /* Specific case for $Extend\ files + * FIXME: Should be made more generic? + */ + else if (ParentId == NTFS_FILE_EXTEND) + { + Display[0] = L'\\'; + Length = wcslen(L"$Extend"); + CopyMemory(&Display[1], L"$Extend", Length * sizeof(WCHAR)); + ++Length; + Display[Length] = L'\\'; + ++Length; + CopyMemory(Display + Length, Name->Name, Name->NameLength * sizeof(WCHAR)); + Length += Name->NameLength; + Display[Length] = UNICODE_NULL; + } + /* Default case */ + else + { + PNAME_CACHE_ENTRY CacheEntry; + + /* Did we already cache the name? */ + for (CacheEntry = CacheHead; CacheEntry != NULL; CacheEntry = CacheEntry->Next) + { + if (ParentId == CacheEntry->MftId) + { + break; + } + } + + /* Nothing written yet */ + Length = 0; + /* We cached it */ + if (CacheEntry != NULL) + { + /* Set up name. The cache entry contains full path */ + Length = CacheEntry->NameLen / sizeof(WCHAR); + CopyMemory(Display, CacheEntry->Name, CacheEntry->NameLen); + Display[Length] = L'\\'; + ++Length; + } + else + { + /* FIXME: Do something, like trying to read parent... */ + _tprintf(_T("Parent: %I64d\n"), ParentId); + } + + /* Copy our name */ + CopyMemory(Display + Length, Name->Name, Name->NameLength * sizeof(WCHAR)); + Length += Name->NameLength; + Display[Length] = UNICODE_NULL; + } + + /* Display the name */ + _tprintf(_T("%s\n"), Display); + + /* If that's a directory, put it in the cache */ + if (Name->FileAttributes & NTFS_FILE_TYPE_DIRECTORY) + { + PNAME_CACHE_ENTRY CacheEntry; + + /* Allocate an entry big enough to store name and cache info */ + CacheEntry = HeapAlloc(GetProcessHeap(), 0, sizeof(NAME_CACHE_ENTRY) + Length * sizeof(WCHAR)); + if (CacheEntry != NULL) + { + /* Insert in head (likely more perf) */ + CacheEntry->Next = CacheHead; + CacheHead = CacheEntry; + /* Set up entry with full path */ + CacheEntry->MftId = MftId; + CacheEntry->NameLen = Length * sizeof(WCHAR); + CopyMemory(CacheEntry->Name, Display, Length * sizeof(WCHAR)); + } + } + + /* Now, just quit */ + FirstRun = FALSE; + Found = TRUE; + + break; + } + + /* If was first run (Win32 search), retry with other names */ + if (FirstRun) + { + FirstRun = FALSE; + goto TryAgain; + } + + /* If we couldn't find a name, print unknown */ + if (!Found) + { + _tprintf(_T("(unknown/unnamed)\n")); + } +} + +PUCHAR DecodeRun(PUCHAR DataRun, LONGLONG *DataRunOffset, ULONGLONG *DataRunLength) +{ + UCHAR DataRunOffsetSize; + UCHAR DataRunLengthSize; + CHAR i; + + /* Get the offset size (in bytes) of the run */ + DataRunOffsetSize = (*DataRun >> 4) & 0xF; + /* Get the length size (in bytes) of the run */ + DataRunLengthSize = *DataRun & 0xF; + + /* Initialize values */ + *DataRunOffset = 0; + *DataRunLength = 0; + + /* Move to next byte */ + DataRun++; + + /* First, extract (byte after byte) run length with the size extracted from header */ + for (i = 0; i < DataRunLengthSize; i++) + { + *DataRunLength += ((ULONG64)*DataRun) << (i * 8); + /* Next byte */ + DataRun++; + } + + /* If offset size is 0, return -1 to show that's sparse run */ + if (DataRunOffsetSize == 0) + { + *DataRunOffset = -1; + } + /* Otherwise, extract offset */ + else + { + /* Extract (byte after byte) run offset with the size extracted from header */ + for (i = 0; i < DataRunOffsetSize - 1; i++) + { + *DataRunOffset += ((ULONG64)*DataRun) << (i * 8); + /* Next byte */ + DataRun++; + } + /* The last byte contains sign so we must process it different way. */ + *DataRunOffset = ((LONG64)(CHAR)(*(DataRun++)) << (i * 8)) + *DataRunOffset; + } + + /* Return next run */ + return DataRun; +} + +void PrintAttributeInfo(PNTFS_ATTR_RECORD Attribute, DWORD MaxSize) +{ + BOOL Known = TRUE; + WCHAR AttributeName[0xFF + 3]; + + /* First of all, try to get attribute name */ + if (Attribute->NameLength != 0 && Attribute->NameOffset < MaxSize && Attribute->NameOffset + Attribute->NameLength < MaxSize) + { + AttributeName[0] = L' '; + CopyMemory(AttributeName + 1, (PUCHAR)((ULONG_PTR)Attribute + Attribute->NameOffset), Attribute->NameLength * sizeof(WCHAR)); + AttributeName[Attribute->NameLength + 1] = L' '; + AttributeName[Attribute->NameLength + 2] = UNICODE_NULL; + } + else + { + AttributeName[0] = L' '; + AttributeName[1] = UNICODE_NULL; + } + + /* Display attribute type, its name (if any) and whether it's resident */ + switch (Attribute->Type) + { + case AttributeFileName: + _tprintf(_T("\t$FILE_NAME%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeStandardInformation: + _tprintf(_T("\t$STANDARD_INFORMATION%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeData: + _tprintf(_T("\t$DATA%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeBitmap: + _tprintf(_T("\t$BITMAP%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeIndexRoot: + _tprintf(_T("\t$INDEX_ROOT%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeIndexAllocation: + _tprintf(_T("\t$INDEX_ALLOCATION%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeObjectId: + _tprintf(_T("\t$OBJECT_ID%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeSecurityDescriptor: + _tprintf(_T("\t$SECURITY_DESCRIPTOR%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeVolumeName: + _tprintf(_T("\t$VOLUME_NAME%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeVolumeInformation: + _tprintf(_T("\t$VOLUME_INFORMATION%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + case AttributeAttributeList: + _tprintf(_T("\t$ATTRIBUTE_LIST%s(%s)\n"), AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + break; + + default: + _tprintf(_T("\tUnknown (%x)%s(%s)\n"), Attribute->Type, AttributeName, (Attribute->IsNonResident ? _T("nonresident") : _T("resident"))); + Known = FALSE; + break; + } + + /* If attribute is non resident, display the logical sectors it covers */ + if (Known && Attribute->IsNonResident) + { + PUCHAR Run; + ULONGLONG Offset = 0; + + /* Get the runs mapping */ + Run = (PUCHAR)((ULONG_PTR)Attribute + Attribute->NonResident.MappingPairsOffset); + /* As long as header isn't 0x00, then, there's a run */ + while (*Run != 0) + { + LONGLONG CurrOffset; + ULONGLONG CurrLen; + + /* Decode the run, and move to the next one */ + Run = DecodeRun(Run, &CurrOffset, &CurrLen); + + /* We don't print sparse runs */ + if (CurrOffset != -1) + { + Offset += CurrOffset; + _tprintf(_T("\t\tlogical sectors %I64d-%I64d (0x%I64x-0x%I64x)\n"), Offset, Offset + CurrLen, Offset, Offset + CurrLen); + } + } + } +} + +int +__cdecl +_tmain(int argc, const TCHAR *argv[]) +{ + TCHAR VolumeName[] = _T("\\\\.\\C:"); + HANDLE VolumeHandle; + NTFS_VOLUME_DATA_BUFFER VolumeInfo; + DWORD LengthReturned; + ULONGLONG File; + PNTFS_FILE_RECORD_OUTPUT_BUFFER OutputBuffer; + TCHAR Letter; + PNAME_CACHE_ENTRY CacheEntry; + + if (argc == 1) + { + PrintUsage(); + return 0; + } + + /* Setup volume name */ + Letter = argv[1][0]; + if ((Letter >= 'A' && Letter <= 'Z') || + (Letter >= 'a' && Letter <= 'z')) + { + VolumeName[4] = Letter; + } + + /* Open volume */ + VolumeHandle = CreateFile(VolumeName, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0 ); + if (VolumeHandle == INVALID_HANDLE_VALUE) + { + _ftprintf(stderr, _T("Failed opening the volume '%s' (%lx)\n"), VolumeName, GetLastError()); + return 1; + } + + /* Get NTFS volume info */ + if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_VOLUME_DATA, NULL, 0, &VolumeInfo, sizeof(VolumeInfo), &LengthReturned, NULL)) + { + _ftprintf(stderr, _T("Failed requesting volume '%s' data (%lx)\n"), VolumeName, GetLastError()); + CloseHandle(VolumeHandle); + return 1; + } + + /* Validate output */ + if (LengthReturned < sizeof(VolumeInfo)) + { + _ftprintf(stderr, _T("Failed reading volume '%s' data (%lx)\n"), VolumeName, GetLastError()); + CloseHandle(VolumeHandle); + return 1; + } + + /* Allocate a buffer big enough to hold a file record */ + OutputBuffer = HeapAlloc(GetProcessHeap(), 0, VolumeInfo.BytesPerFileRecordSegment + sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER)); + if (OutputBuffer == NULL) + { + _ftprintf(stderr, _T("Failed to allocate %x bytes\n"), VolumeInfo.BytesPerFileRecordSegment + sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER)); + CloseHandle(VolumeHandle); + return 1; + } + + /* Forever loop, extract all the files! */ + for (File = 0;; ++File) + { + NTFS_FILE_RECORD_INPUT_BUFFER InputBuffer; + PFILE_RECORD_HEADER FileRecord; + PNTFS_ATTR_RECORD Attribute, AttributesEnd; + + /* Get the file record */ + InputBuffer.FileReferenceNumber.QuadPart = File; + if (!DeviceIoControl(VolumeHandle, FSCTL_GET_NTFS_FILE_RECORD, &InputBuffer, sizeof(InputBuffer), + OutputBuffer, VolumeInfo.BytesPerFileRecordSegment + sizeof(NTFS_FILE_RECORD_OUTPUT_BUFFER), + &LengthReturned, NULL)) + { + continue; + } + + /* Don't deal with it if we already browsed it + * FSCTL_GET_NTFS_FILE_RECORD always returns previous record if demanded + * isn't allocated + */ + if (OutputBuffer->FileReferenceNumber.QuadPart != File) + { + continue; + } + + /* Sanity check */ + FileRecord = (PFILE_RECORD_HEADER)OutputBuffer->FileRecordBuffer; + if (FileRecord->Ntfs.Type != NRH_FILE_TYPE) + { + continue; + } + + /* Print ID */ + _tprintf(_T("\nFile %I64d\n"), OutputBuffer->FileReferenceNumber.QuadPart); + + /* Get attributes list */ + Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->AttributeOffset); + AttributesEnd = (PNTFS_ATTR_RECORD)((ULONG_PTR)FileRecord + FileRecord->BytesInUse); + + /* Print the file name */ + PrintPrettyName(Attribute, AttributesEnd, File); + + /* And print attributes information for each attribute */ + while (Attribute < AttributesEnd && Attribute->Type != AttributeEnd) + { + PrintAttributeInfo(Attribute, VolumeInfo.BytesPerFileRecordSegment); + Attribute = (PNTFS_ATTR_RECORD)((ULONG_PTR)Attribute + Attribute->Length); + } + } + + /* Free memory! */ + while (CacheHead != NULL) + { + CacheEntry = CacheHead; + CacheHead = CacheEntry->Next; + HeapFree(GetProcessHeap(), 0, CacheEntry); + } + + /* Cleanup and exit */ + HeapFree(GetProcessHeap(), 0, OutputBuffer); + CloseHandle(VolumeHandle); + return 0; +} diff --git a/modules/rosapps/applications/rosinternals/nfi/nfi.rc b/modules/rosapps/applications/rosinternals/nfi/nfi.rc new file mode 100644 index 0000000000..89e0d39042 --- /dev/null +++ b/modules/rosapps/applications/rosinternals/nfi/nfi.rc @@ -0,0 +1,4 @@ +#define REACTOS_STR_FILE_DESCRIPTION "NTFS File sector Information\0" +#define REACTOS_STR_INTERNAL_NAME "nfi\0" +#define REACTOS_STR_ORIGINAL_FILENAME "nfi.exe\0" +#include <reactos/version.rc>
6 years, 11 months
1
0
0
0
01/01: [WINHTTP_WINETEST] Sync with Wine 3.0. CORE-14225
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=69d123ae2547edb8b80d0…
commit 69d123ae2547edb8b80d013fe6e2ecd3bf3a8b47 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Jan 20 13:56:09 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Jan 20 13:56:09 2018 +0100 [WINHTTP_WINETEST] Sync with Wine 3.0. CORE-14225 --- modules/rostests/winetests/winhttp/notification.c | 6 +- modules/rostests/winetests/winhttp/winhttp.c | 71 ++++++++++++++++++++++- 2 files changed, 72 insertions(+), 5 deletions(-) diff --git a/modules/rostests/winetests/winhttp/notification.c b/modules/rostests/winetests/winhttp/notification.c index 79f6b8c935..bcb7a0b318 100644 --- a/modules/rostests/winetests/winhttp/notification.c +++ b/modules/rostests/winetests/winhttp/notification.c @@ -944,7 +944,7 @@ static void _read_request_data(struct test_request *req, struct info *info, cons WaitForSingleObject( info->wait, INFINITE ); len = strlen(expected_data); - ok(!memcmp(buffer, expected_data, len), "unexpeceted data\n"); + ok(!memcmp(buffer, expected_data, len), "unexpected data\n"); } static void test_persistent_connection(int port) @@ -1033,14 +1033,16 @@ START_TEST (notification) ret = WaitForSingleObject( si.event, 10000 ); ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError()); if (ret != WAIT_OBJECT_0) + { + CloseHandle(thread); return; + } #ifdef __REACTOS__ if (!winetest_interactive) { skip("Skipping test_persistent_connection due to hang. See ROSTESTS-295.\n"); } -else #endif test_persistent_connection( si.port ); diff --git a/modules/rostests/winetests/winhttp/winhttp.c b/modules/rostests/winetests/winhttp/winhttp.c index 8b2b601ba6..d9024dfb7d 100644 --- a/modules/rostests/winetests/winhttp/winhttp.c +++ b/modules/rostests/winetests/winhttp/winhttp.c @@ -326,7 +326,7 @@ static void test_SendRequest (void) static CHAR post_data[] = "mode=Test"; static const char test_post[] = "mode => Test\0\n"; HINTERNET session, request, connection; - DWORD header_len, optional_len, total_len, bytes_rw, size, err; + DWORD header_len, optional_len, total_len, bytes_rw, size, err, disable; DWORD_PTR context; BOOL ret; CHAR buffer[256]; @@ -357,6 +357,12 @@ static void test_SendRequest (void) ret = WinHttpSetOption(request, WINHTTP_OPTION_CONTEXT_VALUE, &context, sizeof(context)); ok(ret, "WinHttpSetOption failed: %u\n", GetLastError()); + /* writing more data than promised by the content-length header causes an error when the connection + is resued, so disable keep-alive */ + disable = WINHTTP_DISABLE_KEEP_ALIVE; + ret = WinHttpSetOption(request, WINHTTP_OPTION_DISABLE_FEATURE, &disable, sizeof(disable)); + ok(ret, "WinHttpSetOption failed: %u\n", GetLastError()); + context++; ret = WinHttpSendRequest(request, content_type, header_len, post_data, optional_len, total_len, context); err = GetLastError(); @@ -575,7 +581,7 @@ static void test_WinHttpAddHeaders(void) SetLastError(0xdeadbeef); ret = WinHttpAddRequestHeaders(request, test_headers[0], -1L, WINHTTP_ADDREQ_FLAG_ADD); err = GetLastError(); - ok(ret, "WinHttpAddRequestHeader failed to add new header, got %d with error %u.\n", ret, err); + ok(ret, "WinHttpAddRequestHeaders failed to add new header, got %d with error %u.\n", ret, err); ok(err == ERROR_SUCCESS || broken(err == 0xdeadbeef) /* < win7 */, "got %u\n", err); index = 0; @@ -981,7 +987,7 @@ static void test_secure_connection(void) { static const char data_start[] = "<!DOCTYPE html PUBLIC"; HINTERNET ses, con, req; - DWORD size, status, policy, bitness, read_size, err, available_size; + DWORD size, status, policy, bitness, read_size, err, available_size, protocols; BOOL ret; CERT_CONTEXT *cert; WINHTTP_CERTIFICATE_INFO info; @@ -994,6 +1000,11 @@ static void test_secure_connection(void) ret = WinHttpSetOption(ses, WINHTTP_OPTION_REDIRECT_POLICY, &policy, sizeof(policy)); ok(ret, "failed to set redirect policy %u\n", GetLastError()); + protocols = WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2; + ret = WinHttpSetOption(ses, WINHTTP_OPTION_SECURE_PROTOCOLS, &protocols, sizeof(protocols)); + err = GetLastError(); + ok(ret || err == ERROR_INVALID_PARAMETER /* < win7 */, "failed to set protocols %u\n", err); + con = WinHttpConnect(ses, test_winehq, 443, 0); ok(con != NULL, "failed to open a connection %u\n", GetLastError()); @@ -2077,6 +2088,7 @@ static const char largeauth[] = static const char unauthorized[] = "Unauthorized"; static const char hello_world[] = "Hello World"; +static const char auth_unseen[] = "Auth Unseen"; struct server_info { @@ -2136,6 +2148,15 @@ static DWORD CALLBACK server_thread(LPVOID param) send(c, okmsg, sizeof okmsg - 1, 0); send(c, page1, sizeof page1 - 1, 0); } + if (strstr(buffer, "/auth_with_creds")) + { + send(c, okauthmsg, sizeof okauthmsg - 1, 0); + if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q=")) + send(c, hello_world, sizeof hello_world - 1, 0); + else + send(c, auth_unseen, sizeof auth_unseen - 1, 0); + continue; + } if (strstr(buffer, "/auth")) { if (strstr(buffer, "Authorization: Basic dXNlcjpwd2Q=")) @@ -2316,6 +2337,7 @@ static void test_basic_request(int port, const WCHAR *verb, const WCHAR *path) static void test_basic_authentication(int port) { static const WCHAR authW[] = {'/','a','u','t','h',0}; + static const WCHAR auth_with_credsW[] = {'/','a','u','t','h','_','w','i','t','h','_','c','r','e','d','s',0}; static WCHAR userW[] = {'u','s','e','r',0}; static WCHAR passW[] = {'p','w','d',0}; static WCHAR pass2W[] = {'p','w','d','2',0}; @@ -2479,6 +2501,45 @@ static void test_basic_authentication(int port) WinHttpCloseHandle(con); WinHttpCloseHandle(ses); + /* now set the credentials first to show that they get sent with the first request */ + ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0); + ok(ses != NULL, "failed to open session %u\n", GetLastError()); + + con = WinHttpConnect(ses, localhostW, port, 0); + ok(con != NULL, "failed to open a connection %u\n", GetLastError()); + + req = WinHttpOpenRequest(con, NULL, auth_with_credsW, NULL, NULL, NULL, 0); + ok(req != NULL, "failed to open a request %u\n", GetLastError()); + + ret = WinHttpSetCredentials(req, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC, userW, passW, NULL); + ok(ret, "failed to set credentials %u\n", GetLastError()); + + ret = WinHttpSendRequest(req, NULL, 0, NULL, 0, 0, 0); + ok(ret, "failed to send request %u\n", GetLastError()); + + ret = WinHttpReceiveResponse(req, NULL); + ok(ret, "failed to receive response %u\n", GetLastError()); + + status = 0xdeadbeef; + size = sizeof(status); + ret = WinHttpQueryHeaders(req, WINHTTP_QUERY_STATUS_CODE|WINHTTP_QUERY_FLAG_NUMBER, NULL, &status, &size, NULL); + ok(ret, "failed to query status code %u\n", GetLastError()); + ok(status == HTTP_STATUS_OK, "request failed unexpectedly %u\n", status); + + size = 0; + ret = WinHttpReadData(req, buffer, sizeof(buffer), &size); + error = GetLastError(); + ok(ret || broken(error == ERROR_WINHTTP_SHUTDOWN || error == ERROR_WINHTTP_TIMEOUT) /* XP */, "failed to read data %u\n", GetLastError()); + if (ret) + { + ok(size == 11, "expected 11, got %u\n", size); + ok(!memcmp(buffer, hello_world, 11), "got %s\n", buffer); + } + + WinHttpCloseHandle(req); + WinHttpCloseHandle(con); + WinHttpCloseHandle(ses); + /* credentials set with WinHttpSetCredentials take precedence over those set through options */ ses = WinHttpOpen(test_useragent, WINHTTP_ACCESS_TYPE_NO_PROXY, NULL, NULL, 0); @@ -4426,7 +4487,10 @@ START_TEST (winhttp) ret = WaitForSingleObject(si.event, 10000); ok(ret == WAIT_OBJECT_0, "failed to start winhttp test server %u\n", GetLastError()); if (ret != WAIT_OBJECT_0) + { + CloseHandle(thread); return; + } test_IWinHttpRequest(si.port); test_connection_info(si.port); @@ -4446,4 +4510,5 @@ START_TEST (winhttp) test_basic_request(si.port, NULL, quitW); WaitForSingleObject(thread, 3000); + CloseHandle(thread); }
6 years, 11 months
1
0
0
0
01/01: [WINHTTP] Sync with Wine 3.0. CORE-14225
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=9048bdf976df38c94e2ad…
commit 9048bdf976df38c94e2adb6faf976ccb83e952c2 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Jan 20 13:55:24 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Jan 20 13:55:24 2018 +0100 [WINHTTP] Sync with Wine 3.0. CORE-14225 --- dll/win32/winhttp/cookie.c | 2 +- dll/win32/winhttp/net.c | 56 +- dll/win32/winhttp/request.c | 2091 ++++++++++++++++++----------------- dll/win32/winhttp/session.c | 38 +- dll/win32/winhttp/winhttp_private.h | 9 +- media/doc/README.WINE | 2 +- 6 files changed, 1116 insertions(+), 1082 deletions(-) diff --git a/dll/win32/winhttp/cookie.c b/dll/win32/winhttp/cookie.c index eb37d6f852..2d2dbf325e 100644 --- a/dll/win32/winhttp/cookie.c +++ b/dll/win32/winhttp/cookie.c @@ -140,7 +140,7 @@ static cookie_t *parse_cookie( const WCHAR *string ) if (*p++ == '=') { - while (*p && *p == ' ') p++; + while (*p == ' ') p++; len = strlenW( p ); while (len && p[len - 1] == ' ') len--; diff --git a/dll/win32/winhttp/net.c b/dll/win32/winhttp/net.c index 5c4ace898c..bf78b22647 100644 --- a/dll/win32/winhttp/net.c +++ b/dll/win32/winhttp/net.c @@ -131,7 +131,7 @@ static int sock_send(int fd, const void *msg, size_t len, int flags) int ret; do { - ret = send(fd, msg, len, flags); + if ((ret = send(fd, msg, len, flags)) == -1) WARN("send error %s\n", strerror(errno)); } while(ret == -1 && errno == EINTR); return ret; @@ -142,7 +142,7 @@ static int sock_recv(int fd, void *msg, size_t len, int flags) int ret; do { - ret = recv(fd, msg, len, flags); + if ((ret = recv(fd, msg, len, flags)) == -1) WARN("recv error %s\n", strerror(errno)); } while(ret == -1 && errno == EINTR); return ret; @@ -241,41 +241,6 @@ static DWORD netconn_verify_cert( PCCERT_CONTEXT cert, WCHAR *server, DWORD secu return err; } -static SecHandle cred_handle; -static BOOL cred_handle_initialized; - -static CRITICAL_SECTION init_sechandle_cs; -static CRITICAL_SECTION_DEBUG init_sechandle_cs_debug = { - 0, 0, &init_sechandle_cs, - { &init_sechandle_cs_debug.ProcessLocksList, - &init_sechandle_cs_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": init_sechandle_cs") } -}; -static CRITICAL_SECTION init_sechandle_cs = { &init_sechandle_cs_debug, -1, 0, 0, 0, 0 }; - -static BOOL ensure_cred_handle(void) -{ - BOOL ret = TRUE; - - EnterCriticalSection(&init_sechandle_cs); - - if(!cred_handle_initialized) { - SECURITY_STATUS res; - - res = AcquireCredentialsHandleW(NULL, (WCHAR*)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, NULL, - NULL, NULL, &cred_handle, NULL); - if(res == SEC_E_OK) { - cred_handle_initialized = TRUE; - }else { - WARN("AcquireCredentialsHandleW failed: %u\n", res); - ret = FALSE; - } - } - - LeaveCriticalSection(&init_sechandle_cs); - return ret; -} - #ifdef __REACTOS__ static BOOL winsock_initialized = FALSE; BOOL netconn_init_winsock() @@ -300,9 +265,6 @@ BOOL netconn_init_winsock() void netconn_unload( void ) { - if(cred_handle_initialized) - FreeCredentialsHandle(&cred_handle); - DeleteCriticalSection(&init_sechandle_cs); #ifndef HAVE_GETADDRINFO DeleteCriticalSection(&cs_gethostbyname); #endif @@ -439,7 +401,7 @@ BOOL netconn_close( netconn_t *conn ) return TRUE; } -BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags ) +BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_flags, CredHandle *cred_handle ) { SecBuffer out_buf = {0, SECBUFFER_TOKEN, NULL}, in_bufs[2] = {{0, SECBUFFER_TOKEN}, {0, SECBUFFER_EMPTY}}; SecBufferDesc out_desc = {SECBUFFER_VERSION, 1, &out_buf}, in_desc = {SECBUFFER_VERSION, 2, in_bufs}; @@ -455,14 +417,11 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl const DWORD isc_req_flags = ISC_REQ_ALLOCATE_MEMORY|ISC_REQ_USE_SESSION_KEY|ISC_REQ_CONFIDENTIALITY |ISC_REQ_SEQUENCE_DETECT|ISC_REQ_REPLAY_DETECT|ISC_REQ_MANUAL_CRED_VALIDATION; - if(!ensure_cred_handle()) - return FALSE; - read_buf = heap_alloc(read_buf_size); if(!read_buf) return FALSE; - status = InitializeSecurityContextW(&cred_handle, NULL, hostname, isc_req_flags, 0, 0, NULL, 0, + status = InitializeSecurityContextW(cred_handle, NULL, hostname, isc_req_flags, 0, 0, NULL, 0, &ctx, &out_desc, &attrs, NULL); assert(status != SEC_E_OK); @@ -514,7 +473,6 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl size = sock_recv(conn->socket, read_buf+in_bufs[0].cbBuffer, read_buf_size-in_bufs[0].cbBuffer, 0); if(size < 1) { - WARN("recv error\n"); status = ERROR_WINHTTP_SECURE_CHANNEL_ERROR; break; } @@ -523,7 +481,7 @@ BOOL netconn_secure_connect( netconn_t *conn, WCHAR *hostname, DWORD security_fl in_bufs[0].cbBuffer += size; in_bufs[0].pvBuffer = read_buf; - status = InitializeSecurityContextW(&cred_handle, &ctx, hostname, isc_req_flags, 0, 0, &in_desc, + status = InitializeSecurityContextW(cred_handle, &ctx, hostname, isc_req_flags, 0, 0, &in_desc, 0, NULL, &out_desc, &attrs, NULL); TRACE("InitializeSecurityContext ret %08x\n", status); @@ -650,10 +608,8 @@ static BOOL read_ssl_chunk(netconn_t *conn, void *buf, SIZE_T buf_size, SIZE_T * conn->extra_buf = NULL; }else { buf_len = sock_recv(conn->socket, conn->ssl_buf+conn->extra_len, ssl_buf_size-conn->extra_len, 0); - if(buf_len < 0) { - WARN("recv failed\n"); + if(buf_len < 0) return FALSE; - } if(!buf_len) { *eof = TRUE; diff --git a/dll/win32/winhttp/request.c b/dll/win32/winhttp/request.c index 128d5cb14c..f3098e34d0 100644 --- a/dll/win32/winhttp/request.c +++ b/dll/win32/winhttp/request.c @@ -29,6 +29,7 @@ #include <winuser.h> #include <httprequest.h> #include <httprequestid.h> +#include <schannel.h> #include "inet_ntop.c" @@ -390,7 +391,7 @@ static BOOL delete_header( request_t *request, DWORD index ) return TRUE; } -BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) +static BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) { int index; header_t hdr; @@ -507,7 +508,7 @@ BOOL WINAPI WinHttpAddRequestHeaders( HINTERNET hrequest, LPCWSTR headers, DWORD BOOL ret; request_t *request; - TRACE("%p, %s, 0x%x, 0x%08x\n", hrequest, debugstr_w(headers), len, flags); + TRACE("%p, %s, %u, 0x%08x\n", hrequest, debugstr_wn(headers, len), len, flags); if (!headers || !len) { @@ -838,1325 +839,1367 @@ BOOL WINAPI WinHttpQueryHeaders( HINTERNET hrequest, DWORD level, LPCWSTR name, return ret; } -static LPWSTR concatenate_string_list( LPCWSTR *list, int len ) -{ - LPCWSTR *t; - LPWSTR str; - - for( t = list; *t ; t++ ) - len += strlenW( *t ); - len++; - - str = heap_alloc( len * sizeof(WCHAR) ); - if (!str) return NULL; - *str = 0; +#undef ARRAYSIZE +#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0])) - for( t = list; *t ; t++ ) - strcatW( str, *t ); +static const WCHAR basicW[] = {'B','a','s','i','c',0}; +static const WCHAR ntlmW[] = {'N','T','L','M',0}; +static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t',0}; +static const WCHAR digestW[] = {'D','i','g','e','s','t',0}; +static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',0}; - return str; +static const struct +{ + const WCHAR *str; + unsigned int len; + DWORD scheme; } +auth_schemes[] = +{ + { basicW, ARRAYSIZE(basicW) - 1, WINHTTP_AUTH_SCHEME_BASIC }, + { ntlmW, ARRAYSIZE(ntlmW) - 1, WINHTTP_AUTH_SCHEME_NTLM }, + { passportW, ARRAYSIZE(passportW) - 1, WINHTTP_AUTH_SCHEME_PASSPORT }, + { digestW, ARRAYSIZE(digestW) - 1, WINHTTP_AUTH_SCHEME_DIGEST }, + { negotiateW, ARRAYSIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE } +}; +static const unsigned int num_auth_schemes = sizeof(auth_schemes)/sizeof(auth_schemes[0]); -static LPWSTR build_header_request_string( request_t *request, LPCWSTR verb, - LPCWSTR path, LPCWSTR version ) +static enum auth_scheme scheme_from_flag( DWORD flag ) { - static const WCHAR crlf[] = {'\r','\n',0}; - static const WCHAR space[] = { ' ',0 }; - static const WCHAR colon[] = { ':',' ',0 }; - static const WCHAR twocrlf[] = {'\r','\n','\r','\n', 0}; - LPWSTR requestString; - DWORD len, n; - LPCWSTR *req; - UINT i; - LPWSTR p; + int i; - /* allocate space for an array of all the string pointers to be added */ - len = (request->num_headers) * 4 + 10; - req = heap_alloc( len * sizeof(LPCWSTR) ); - if (!req) return NULL; + for (i = 0; i < num_auth_schemes; i++) if (flag == auth_schemes[i].scheme) return i; + return SCHEME_INVALID; +} - /* add the verb, path and HTTP version string */ - n = 0; - req[n++] = verb; - req[n++] = space; - req[n++] = path; - req[n++] = space; - req[n++] = version; +static DWORD auth_scheme_from_header( WCHAR *header ) +{ + unsigned int i; - /* Append custom request headers */ - for (i = 0; i < request->num_headers; i++) + for (i = 0; i < num_auth_schemes; i++) { - if (request->headers[i].is_request) - { - req[n++] = crlf; - req[n++] = request->headers[i].field; - req[n++] = colon; - req[n++] = request->headers[i].value; - - TRACE("Adding custom header %s (%s)\n", - debugstr_w(request->headers[i].field), - debugstr_w(request->headers[i].value)); - } + if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) && + (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme; } - - if( n >= len ) - ERR("oops. buffer overrun\n"); - - req[n] = NULL; - requestString = concatenate_string_list( req, 4 ); - heap_free( req ); - if (!requestString) return NULL; - - /* - * Set (header) termination string for request - * Make sure there are exactly two new lines at the end of the request - */ - p = &requestString[strlenW(requestString)-1]; - while ( (*p == '\n') || (*p == '\r') ) - p--; - strcpyW( p+1, twocrlf ); - - return requestString; + return 0; } -static BOOL read_reply( request_t *request ); - -static BOOL secure_proxy_connect( request_t *request ) +static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD supported, LPDWORD first ) { - static const WCHAR verbConnect[] = {'C','O','N','N','E','C','T',0}; - static const WCHAR fmt[] = {'%','s',':','%','u',0}; + DWORD index = 0, supported_schemes = 0, first_scheme = 0; BOOL ret = FALSE; - LPWSTR path; - connect_t *connect = request->connect; - path = heap_alloc( (strlenW( connect->hostname ) + 13) * sizeof(WCHAR) ); - if (path) + for (;;) { - LPWSTR requestString; - - sprintfW( path, fmt, connect->hostname, connect->hostport ); - requestString = build_header_request_string( request, verbConnect, - path, http1_1 ); - heap_free( path ); - if (requestString) - { - LPSTR req_ascii = strdupWA( requestString ); + WCHAR *buffer; + DWORD size, scheme; - heap_free( requestString ); - if (req_ascii) - { - int len = strlen( req_ascii ), bytes_sent; + size = 0; + query_headers( request, level, NULL, NULL, &size, &index ); + if (get_last_error() != ERROR_INSUFFICIENT_BUFFER) break; - ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent ); - heap_free( req_ascii ); - if (ret) - ret = read_reply( request ); - } + index--; + if (!(buffer = heap_alloc( size ))) return FALSE; + if (!query_headers( request, level, NULL, buffer, &size, &index )) + { + heap_free( buffer ); + return FALSE; } - } - return ret; -} + scheme = auth_scheme_from_header( buffer ); + heap_free( buffer ); + if (!scheme) continue; -#ifndef INET6_ADDRSTRLEN -#define INET6_ADDRSTRLEN 46 -#endif + if (!first_scheme) first_scheme = scheme; + supported_schemes |= scheme; -static WCHAR *addr_to_str( struct sockaddr_storage *addr ) -{ - char buf[INET6_ADDRSTRLEN]; - void *src; + ret = TRUE; + } - switch (addr->ss_family) + if (ret) { - case AF_INET: - src = &((struct sockaddr_in *)addr)->sin_addr; - break; - case AF_INET6: - src = &((struct sockaddr_in6 *)addr)->sin6_addr; - break; - default: - WARN("unsupported address family %d\n", addr->ss_family); - return NULL; + *supported = supported_schemes; + *first = first_scheme; } - if (!inet_ntop( addr->ss_family, src, buf, sizeof(buf) )) return NULL; - return strdupAW( buf ); + return ret; } -static CRITICAL_SECTION connection_pool_cs; -static CRITICAL_SECTION_DEBUG connection_pool_debug = +/*********************************************************************** + * WinHttpQueryAuthSchemes (winhttp.@) + */ +BOOL WINAPI WinHttpQueryAuthSchemes( HINTERNET hrequest, LPDWORD supported, LPDWORD first, LPDWORD target ) { - 0, 0, &connection_pool_cs, - { &connection_pool_debug.ProcessLocksList, &connection_pool_debug.ProcessLocksList }, - 0, 0, { (DWORD_PTR)(__FILE__ ": connection_pool_cs") } -}; -static CRITICAL_SECTION connection_pool_cs = { &connection_pool_debug, -1, 0, 0, 0, 0 }; + BOOL ret = FALSE; + request_t *request; -static struct list connection_pool = LIST_INIT( connection_pool ); + TRACE("%p, %p, %p, %p\n", hrequest, supported, first, target); -void release_host( hostdata_t *host ) -{ - LONG ref; + if (!(request = (request_t *)grab_object( hrequest ))) + { + set_last_error( ERROR_INVALID_HANDLE ); + return FALSE; + } + if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) + { + release_object( &request->hdr ); + set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); + return FALSE; + } + if (!supported || !first || !target) + { + release_object( &request->hdr ); + set_last_error( ERROR_INVALID_PARAMETER ); + return FALSE; - EnterCriticalSection( &connection_pool_cs ); - if (!(ref = --host->ref)) list_remove( &host->entry ); - LeaveCriticalSection( &connection_pool_cs ); - if (ref) return; + } - assert( list_empty( &host->connections ) ); - heap_free( host->hostname ); - heap_free( host ); -} + if (query_auth_schemes( request, WINHTTP_QUERY_WWW_AUTHENTICATE, supported, first )) + { + *target = WINHTTP_AUTH_TARGET_SERVER; + ret = TRUE; + } + else if (query_auth_schemes( request, WINHTTP_QUERY_PROXY_AUTHENTICATE, supported, first )) + { + *target = WINHTTP_AUTH_TARGET_PROXY; + ret = TRUE; + } -static BOOL connection_collector_running; + release_object( &request->hdr ); + if (ret) set_last_error( ERROR_SUCCESS ); + return ret; +} -static DWORD WINAPI connection_collector(void *arg) +static UINT encode_base64( const char *bin, unsigned int len, WCHAR *base64 ) { - unsigned int remaining_connections; - netconn_t *netconn, *next_netconn; - hostdata_t *host, *next_host; - ULONGLONG now; + UINT n = 0, x; + static const char base64enc[] = + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - do + while (len > 0) { - /* FIXME: Use more sophisticated method */ - Sleep(5000); - remaining_connections = 0; - now = GetTickCount64(); - - EnterCriticalSection(&connection_pool_cs); + /* first 6 bits, all from bin[0] */ + base64[n++] = base64enc[(bin[0] & 0xfc) >> 2]; + x = (bin[0] & 3) << 4; - LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, hostdata_t, entry) - { - LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections, netconn_t, entry) - { - if (netconn->keep_until < now) - { - TRACE("freeing %p\n", netconn); - list_remove(&netconn->entry); - netconn_close(netconn); - } - else - { - remaining_connections++; - } - } + /* next 6 bits, 2 from bin[0] and 4 from bin[1] */ + if (len == 1) + { + base64[n++] = base64enc[x]; + base64[n++] = '='; + base64[n++] = '='; + break; } + base64[n++] = base64enc[x | ((bin[1] & 0xf0) >> 4)]; + x = (bin[1] & 0x0f) << 2; - if (!remaining_connections) connection_collector_running = FALSE; - - LeaveCriticalSection(&connection_pool_cs); - } while(remaining_connections); + /* next 6 bits 4 from bin[1] and 2 from bin[2] */ + if (len == 2) + { + base64[n++] = base64enc[x]; + base64[n++] = '='; + break; + } + base64[n++] = base64enc[x | ((bin[2] & 0xc0) >> 6)]; - FreeLibraryAndExitThread( winhttp_instance, 0 ); + /* last 6 bits, all from bin [2] */ + base64[n++] = base64enc[bin[2] & 0x3f]; + bin += 3; + len -= 3; + } + base64[n] = 0; + return n; } -static void cache_connection( netconn_t *netconn ) +static inline char decode_char( WCHAR c ) { - TRACE( "caching connection %p\n", netconn ); + if (c >= 'A' && c <= 'Z') return c - 'A'; + if (c >= 'a' && c <= 'z') return c - 'a' + 26; + if (c >= '0' && c <= '9') return c - '0' + 52; + if (c == '+') return 62; + if (c == '/') return 63; + return 64; +} - EnterCriticalSection( &connection_pool_cs ); +static unsigned int decode_base64( const WCHAR *base64, unsigned int len, char *buf ) +{ + unsigned int i = 0; + char c0, c1, c2, c3; + const WCHAR *p = base64; - netconn->keep_until = GetTickCount64() + DEFAULT_KEEP_ALIVE_TIMEOUT; - list_add_head( &netconn->host->connections, &netconn->entry ); + while (len > 4) + { + if ((c0 = decode_char( p[0] )) > 63) return 0; + if ((c1 = decode_char( p[1] )) > 63) return 0; + if ((c2 = decode_char( p[2] )) > 63) return 0; + if ((c3 = decode_char( p[3] )) > 63) return 0; - if (!connection_collector_running) + if (buf) + { + buf[i + 0] = (c0 << 2) | (c1 >> 4); + buf[i + 1] = (c1 << 4) | (c2 >> 2); + buf[i + 2] = (c2 << 6) | c3; + } + len -= 4; + i += 3; + p += 4; + } + if (p[2] == '=') { - HMODULE module; - HANDLE thread; + if ((c0 = decode_char( p[0] )) > 63) return 0; + if ((c1 = decode_char( p[1] )) > 63) return 0; - GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)winhttp_instance, &module ); + if (buf) buf[i] = (c0 << 2) | (c1 >> 4); + i++; + } + else if (p[3] == '=') + { + if ((c0 = decode_char( p[0] )) > 63) return 0; + if ((c1 = decode_char( p[1] )) > 63) return 0; + if ((c2 = decode_char( p[2] )) > 63) return 0; - thread = CreateThread(NULL, 0, connection_collector, NULL, 0, NULL); - if (thread) + if (buf) { - CloseHandle( thread ); - connection_collector_running = TRUE; + buf[i + 0] = (c0 << 2) | (c1 >> 4); + buf[i + 1] = (c1 << 4) | (c2 >> 2); } - else + i += 2; + } + else + { + if ((c0 = decode_char( p[0] )) > 63) return 0; + if ((c1 = decode_char( p[1] )) > 63) return 0; + if ((c2 = decode_char( p[2] )) > 63) return 0; + if ((c3 = decode_char( p[3] )) > 63) return 0; + + if (buf) { - FreeLibrary( winhttp_instance ); + buf[i + 0] = (c0 << 2) | (c1 >> 4); + buf[i + 1] = (c1 << 4) | (c2 >> 2); + buf[i + 2] = (c2 << 6) | c3; } + i += 3; } - - LeaveCriticalSection( &connection_pool_cs ); + return i; } -static BOOL open_connection( request_t *request ) +static struct authinfo *alloc_authinfo(void) { - BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE; - hostdata_t *host = NULL, *iter; - netconn_t *netconn = NULL; - connect_t *connect; - WCHAR *addressW = NULL; - INTERNET_PORT port; - DWORD len; + struct authinfo *ret; - if (request->netconn) goto done; + if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL; - connect = request->connect; - port = connect->serverport ? connect->serverport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80); + SecInvalidateHandle( &ret->cred ); + SecInvalidateHandle( &ret->ctx ); + memset( &ret->exp, 0, sizeof(ret->exp) ); + ret->scheme = 0; + ret->attr = 0; + ret->max_token = 0; + ret->data = NULL; + ret->data_len = 0; + ret->finished = FALSE; + return ret; +} - EnterCriticalSection( &connection_pool_cs ); +void destroy_authinfo( struct authinfo *authinfo ) +{ + if (!authinfo) return; - LIST_FOR_EACH_ENTRY( iter, &connection_pool, hostdata_t, entry ) - { - if (iter->port == port && !strcmpW( connect->servername, iter->hostname ) && !is_secure == !iter->secure) - { - host = iter; - host->ref++; - break; - } - } + if (SecIsValidHandle( &authinfo->ctx )) + DeleteSecurityContext( &authinfo->ctx ); + if (SecIsValidHandle( &authinfo->cred )) + FreeCredentialsHandle( &authinfo->cred ); - if (!host) + heap_free( authinfo->data ); + heap_free( authinfo ); +} + +static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR *buffer, DWORD len ) +{ + DWORD size, index = 0; + for (;;) { - if ((host = heap_alloc( sizeof(*host) ))) - { - host->ref = 1; - host->secure = is_secure; - host->port = port; - list_init( &host->connections ); - if ((host->hostname = strdupW( connect->servername ))) - { - list_add_head( &connection_pool, &host->entry ); - } - else - { - heap_free( host ); - host = NULL; - } - } + size = len; + if (!query_headers( request, level, NULL, buffer, &size, &index )) return FALSE; + if (auth_scheme_from_header( buffer ) == scheme) break; } + return TRUE; +} - LeaveCriticalSection( &connection_pool_cs ); +static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_flag ) +{ + struct authinfo *authinfo, **auth_ptr; + enum auth_scheme scheme = scheme_from_flag( scheme_flag ); + const WCHAR *auth_target, *username, *password; + WCHAR auth_value[2048], *auth_reply; + DWORD len = sizeof(auth_value), len_scheme, flags; + BOOL ret, has_auth_value; - if (!host) return FALSE; + if (scheme == SCHEME_INVALID) return FALSE; - for (;;) + switch (target) { - EnterCriticalSection( &connection_pool_cs ); - if (!list_empty( &host->connections )) + case WINHTTP_AUTH_TARGET_SERVER: + has_auth_value = get_authvalue( request, WINHTTP_QUERY_WWW_AUTHENTICATE, scheme_flag, auth_value, len ); + auth_ptr = &request->authinfo; + auth_target = attr_authorization; + if (request->creds[TARGET_SERVER][scheme].username) { - netconn = LIST_ENTRY( list_head( &host->connections ), netconn_t, entry ); - list_remove( &netconn->entry ); + if (scheme != SCHEME_BASIC && !has_auth_value) return FALSE; + username = request->creds[TARGET_SERVER][scheme].username; + password = request->creds[TARGET_SERVER][scheme].password; } - LeaveCriticalSection( &connection_pool_cs ); - if (!netconn) break; + else + { + if (!has_auth_value) return FALSE; + username = request->connect->username; + password = request->connect->password; + } + break; - if (netconn_is_alive( netconn )) break; - TRACE("connection %p no longer alive, closing\n", netconn); - netconn_close( netconn ); - netconn = NULL; - } + case WINHTTP_AUTH_TARGET_PROXY: + if (!get_authvalue( request, WINHTTP_QUERY_PROXY_AUTHENTICATE, scheme_flag, auth_value, len )) + return FALSE; + auth_ptr = &request->proxy_authinfo; + auth_target = attr_proxy_authorization; + if (request->creds[TARGET_PROXY][scheme].username) + { + username = request->creds[TARGET_PROXY][scheme].username; + password = request->creds[TARGET_PROXY][scheme].password; + } + else + { + username = request->connect->session->proxy_username; + password = request->connect->session->proxy_password; + } + break; - if (!connect->resolved && netconn) - { - connect->sockaddr = netconn->sockaddr; - connect->resolved = TRUE; + default: + WARN("unknown target %x\n", target); + return FALSE; } + authinfo = *auth_ptr; - if (!connect->resolved) + switch (scheme) { - len = strlenW( host->hostname ) + 1; - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, host->hostname, len ); + case SCHEME_BASIC: + { + int userlen, passlen; - if (!netconn_resolve( host->hostname, port, &connect->sockaddr, request->resolve_timeout )) - { - release_host( host ); - return FALSE; - } - connect->resolved = TRUE; + if (!username || !password) return FALSE; + if ((!authinfo && !(authinfo = alloc_authinfo())) || authinfo->finished) return FALSE; - if (!(addressW = addr_to_str( &connect->sockaddr ))) - { - release_host( host ); - return FALSE; - } - len = strlenW( addressW ) + 1; - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, addressW, len ); - } + userlen = WideCharToMultiByte( CP_UTF8, 0, username, strlenW( username ), NULL, 0, NULL, NULL ); + passlen = WideCharToMultiByte( CP_UTF8, 0, password, strlenW( password ), NULL, 0, NULL, NULL ); - if (!netconn) + authinfo->data_len = userlen + 1 + passlen; + if (!(authinfo->data = heap_alloc( authinfo->data_len ))) return FALSE; + + WideCharToMultiByte( CP_UTF8, 0, username, -1, authinfo->data, userlen, NULL, NULL ); + authinfo->data[userlen] = ':'; + WideCharToMultiByte( CP_UTF8, 0, password, -1, authinfo->data + userlen + 1, passlen, NULL, NULL ); + + authinfo->scheme = SCHEME_BASIC; + authinfo->finished = TRUE; + break; + } + case SCHEME_NTLM: + case SCHEME_NEGOTIATE: { - if (!addressW && !(addressW = addr_to_str( &connect->sockaddr ))) + SECURITY_STATUS status; + SecBufferDesc out_desc, in_desc; + SecBuffer out, in; + ULONG flags = ISC_REQ_CONNECTION|ISC_REQ_USE_DCE_STYLE|ISC_REQ_MUTUAL_AUTH|ISC_REQ_DELEGATE; + const WCHAR *p; + BOOL first = FALSE; + + if (!authinfo) { - release_host( host ); - return FALSE; - } + TimeStamp exp; + SEC_WINNT_AUTH_IDENTITY_W id; + WCHAR *domain, *user; - TRACE("connecting to %s:%u\n", debugstr_w(addressW), port); + if (!username || !password || !(authinfo = alloc_authinfo())) return FALSE; - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, addressW, 0 ); + first = TRUE; + domain = (WCHAR *)username; + user = strchrW( username, '\\' ); - if (!(netconn = netconn_create( host, &connect->sockaddr, request->connect_timeout ))) - { - heap_free( addressW ); - release_host( host ); - return FALSE; - } - netconn_set_timeout( netconn, TRUE, request->send_timeout ); - netconn_set_timeout( netconn, FALSE, request->recv_timeout ); - if (is_secure) - { - if (connect->session->proxy_server && - strcmpiW( connect->hostname, connect->servername )) + if (user) user++; + else { - if (!secure_proxy_connect( request )) + user = (WCHAR *)username; + domain = NULL; + } + id.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; + id.User = user; + id.UserLength = strlenW( user ); + id.Domain = domain; + id.DomainLength = domain ? user - domain - 1 : 0; + id.Password = (WCHAR *)password; + id.PasswordLength = strlenW( password ); + + status = AcquireCredentialsHandleW( NULL, (SEC_WCHAR *)auth_schemes[scheme].str, + SECPKG_CRED_OUTBOUND, NULL, &id, NULL, NULL, + &authinfo->cred, &exp ); + if (status == SEC_E_OK) + { + PSecPkgInfoW info; + status = QuerySecurityPackageInfoW( (SEC_WCHAR *)auth_schemes[scheme].str, &info ); + if (status == SEC_E_OK) { - heap_free( addressW ); - netconn_close( netconn ); - return FALSE; + authinfo->max_token = info->cbMaxToken; + FreeContextBuffer( info ); } } - if (!netconn_secure_connect( netconn, connect->hostname, request->security_flags )) + if (status != SEC_E_OK) { - heap_free( addressW ); - netconn_close( netconn ); + WARN("AcquireCredentialsHandleW for scheme %s failed with error 0x%08x\n", + debugstr_w(auth_schemes[scheme].str), status); + heap_free( authinfo ); return FALSE; } + authinfo->scheme = scheme; } + else if (authinfo->finished) return FALSE; - request->netconn = netconn; - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, strlenW(addressW) + 1 ); - } - else - { - TRACE("using connection %p\n", netconn); + if ((strlenW( auth_value ) < auth_schemes[authinfo->scheme].len || + strncmpiW( auth_value, auth_schemes[authinfo->scheme].str, auth_schemes[authinfo->scheme].len ))) + { + ERR("authentication scheme changed from %s to %s\n", + debugstr_w(auth_schemes[authinfo->scheme].str), debugstr_w(auth_value)); + destroy_authinfo( authinfo ); + *auth_ptr = NULL; + return FALSE; + } + in.BufferType = SECBUFFER_TOKEN; + in.cbBuffer = 0; + in.pvBuffer = NULL; - netconn_set_timeout( netconn, TRUE, request->send_timeout ); - netconn_set_timeout( netconn, FALSE, request->recv_timeout ); - request->netconn = netconn; + in_desc.ulVersion = 0; + in_desc.cBuffers = 1; + in_desc.pBuffers = ∈ + + p = auth_value + auth_schemes[scheme].len; + if (*p == ' ') + { + int len = strlenW( ++p ); + in.cbBuffer = decode_base64( p, len, NULL ); + if (!(in.pvBuffer = heap_alloc( in.cbBuffer ))) { + destroy_authinfo( authinfo ); + *auth_ptr = NULL; + return FALSE; + } + decode_base64( p, len, in.pvBuffer ); + } + out.BufferType = SECBUFFER_TOKEN; + out.cbBuffer = authinfo->max_token; + if (!(out.pvBuffer = heap_alloc( authinfo->max_token ))) + { + heap_free( in.pvBuffer ); + destroy_authinfo( authinfo ); + *auth_ptr = NULL; + return FALSE; + } + out_desc.ulVersion = 0; + out_desc.cBuffers = 1; + out_desc.pBuffers = &out; + + status = InitializeSecurityContextW( first ? &authinfo->cred : NULL, first ? NULL : &authinfo->ctx, + first ? request->connect->servername : NULL, flags, 0, + SECURITY_NETWORK_DREP, in.pvBuffer ? &in_desc : NULL, 0, + &authinfo->ctx, &out_desc, &authinfo->attr, &authinfo->exp ); + heap_free( in.pvBuffer ); + if (status == SEC_E_OK) + { + heap_free( authinfo->data ); + authinfo->data = out.pvBuffer; + authinfo->data_len = out.cbBuffer; + authinfo->finished = TRUE; + TRACE("sending last auth packet\n"); + } + else if (status == SEC_I_CONTINUE_NEEDED) + { + heap_free( authinfo->data ); + authinfo->data = out.pvBuffer; + authinfo->data_len = out.cbBuffer; + TRACE("sending next auth packet\n"); + } + else + { + ERR("InitializeSecurityContextW failed with error 0x%08x\n", status); + heap_free( out.pvBuffer ); + destroy_authinfo( authinfo ); + *auth_ptr = NULL; + return FALSE; + } + break; + } + default: + ERR("invalid scheme %u\n", scheme); + return FALSE; } + *auth_ptr = authinfo; -done: - request->read_pos = request->read_size = 0; - request->read_chunked = FALSE; - request->read_chunked_size = ~0u; - request->read_chunked_eof = FALSE; - heap_free( addressW ); - return TRUE; -} + len_scheme = auth_schemes[authinfo->scheme].len; + len = len_scheme + 1 + ((authinfo->data_len + 2) * 4) / 3; + if (!(auth_reply = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE; -void close_connection( request_t *request ) -{ - if (!request->netconn) return; + memcpy( auth_reply, auth_schemes[authinfo->scheme].str, len_scheme * sizeof(WCHAR) ); + auth_reply[len_scheme] = ' '; + encode_base64( authinfo->data, authinfo->data_len, auth_reply + len_scheme + 1 ); - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 0 ); - netconn_close( request->netconn ); - request->netconn = NULL; - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 ); + flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE; + ret = process_header( request, auth_target, auth_reply, flags, TRUE ); + heap_free( auth_reply ); + return ret; } -static BOOL add_host_header( request_t *request, DWORD modifier ) +static LPWSTR concatenate_string_list( LPCWSTR *list, int len ) { - BOOL ret; - DWORD len; - WCHAR *host; - static const WCHAR fmt[] = {'%','s',':','%','u',0}; - connect_t *connect = request->connect; - INTERNET_PORT port; + LPCWSTR *t; + LPWSTR str; - port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80); + for( t = list; *t ; t++ ) + len += strlenW( *t ); + len++; - if (port == INTERNET_DEFAULT_HTTP_PORT || port == INTERNET_DEFAULT_HTTPS_PORT) - { - return process_header( request, attr_host, connect->hostname, modifier, TRUE ); - } - len = strlenW( connect->hostname ) + 7; /* sizeof(":65335") */ - if (!(host = heap_alloc( len * sizeof(WCHAR) ))) return FALSE; - sprintfW( host, fmt, connect->hostname, port ); - ret = process_header( request, attr_host, host, modifier, TRUE ); - heap_free( host ); - return ret; -} + str = heap_alloc( len * sizeof(WCHAR) ); + if (!str) return NULL; + *str = 0; -static void clear_response_headers( request_t *request ) -{ - unsigned int i; + for( t = list; *t ; t++ ) + strcatW( str, *t ); - for (i = 0; i < request->num_headers; i++) - { - if (!request->headers[i].field) continue; - if (!request->headers[i].value) continue; - if (request->headers[i].is_request) continue; - delete_header( request, i ); - i--; - } + return str; } -/* remove some amount of data from the read buffer */ -static void remove_data( request_t *request, int count ) +static LPWSTR build_header_request_string( request_t *request, LPCWSTR verb, + LPCWSTR path, LPCWSTR version ) { - if (!(request->read_size -= count)) request->read_pos = 0; - else request->read_pos += count; -} + static const WCHAR crlf[] = {'\r','\n',0}; + static const WCHAR space[] = { ' ',0 }; + static const WCHAR colon[] = { ':',' ',0 }; + static const WCHAR twocrlf[] = {'\r','\n','\r','\n', 0}; + LPWSTR requestString; + DWORD len, n; + LPCWSTR *req; + UINT i; + LPWSTR p; -/* read some more data into the read buffer */ -static BOOL read_more_data( request_t *request, int maxlen, BOOL notify ) -{ - int len; - BOOL ret; + /* allocate space for an array of all the string pointers to be added */ + len = (request->num_headers) * 4 + 10; + req = heap_alloc( len * sizeof(LPCWSTR) ); + if (!req) return NULL; - if (request->read_chunked_eof) return FALSE; + /* add the verb, path and HTTP version string */ + n = 0; + req[n++] = verb; + req[n++] = space; + req[n++] = path; + req[n++] = space; + req[n++] = version; - if (request->read_size && request->read_pos) + /* Append custom request headers */ + for (i = 0; i < request->num_headers; i++) { - /* move existing data to the start of the buffer */ - memmove( request->read_buf, request->read_buf + request->read_pos, request->read_size ); - request->read_pos = 0; + if (request->headers[i].is_request) + { + req[n++] = crlf; + req[n++] = request->headers[i].field; + req[n++] = colon; + req[n++] = request->headers[i].value; + + TRACE("Adding custom header %s (%s)\n", + debugstr_w(request->headers[i].field), + debugstr_w(request->headers[i].value)); + } } - if (maxlen == -1) maxlen = sizeof(request->read_buf); - if (notify) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 ); + if( n >= len ) + ERR("oops. buffer overrun\n"); - ret = netconn_recv( request->netconn, request->read_buf + request->read_size, - maxlen - request->read_size, 0, &len ); + req[n] = NULL; + requestString = concatenate_string_list( req, 4 ); + heap_free( req ); + if (!requestString) return NULL; - if (notify) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, &len, sizeof(len) ); + /* + * Set (header) termination string for request + * Make sure there are exactly two new lines at the end of the request + */ + p = &requestString[strlenW(requestString)-1]; + while ( (*p == '\n') || (*p == '\r') ) + p--; + strcpyW( p+1, twocrlf ); - request->read_size += len; - return ret; + return requestString; } -/* discard data contents until we reach end of line */ -static BOOL discard_eol( request_t *request, BOOL notify ) -{ - do - { - char *eol = memchr( request->read_buf + request->read_pos, '\n', request->read_size ); - if (eol) - { - remove_data( request, (eol + 1) - (request->read_buf + request->read_pos) ); - break; - } - request->read_pos = request->read_size = 0; /* discard everything */ - if (!read_more_data( request, -1, notify )) return FALSE; - } while (request->read_size); - return TRUE; -} +static BOOL read_reply( request_t *request ); -/* read the size of the next chunk */ -static BOOL start_next_chunk( request_t *request, BOOL notify ) +static BOOL secure_proxy_connect( request_t *request ) { - DWORD chunk_size = 0; - - assert(!request->read_chunked_size || request->read_chunked_size == ~0u); - - if (request->read_chunked_eof) return FALSE; - - /* read terminator for the previous chunk */ - if (!request->read_chunked_size && !discard_eol( request, notify )) return FALSE; + static const WCHAR verbConnect[] = {'C','O','N','N','E','C','T',0}; + static const WCHAR fmt[] = {'%','s',':','%','u',0}; + BOOL ret = FALSE; + LPWSTR path; + connect_t *connect = request->connect; - for (;;) + path = heap_alloc( (strlenW( connect->hostname ) + 13) * sizeof(WCHAR) ); + if (path) { - while (request->read_size) - { - char ch = request->read_buf[request->read_pos]; - if (ch >= '0' && ch <= '9') chunk_size = chunk_size * 16 + ch - '0'; - else if (ch >= 'a' && ch <= 'f') chunk_size = chunk_size * 16 + ch - 'a' + 10; - else if (ch >= 'A' && ch <= 'F') chunk_size = chunk_size * 16 + ch - 'A' + 10; - else if (ch == ';' || ch == '\r' || ch == '\n') - { - TRACE("reading %u byte chunk\n", chunk_size); + LPWSTR requestString; - if (request->content_length == ~0u) request->content_length = chunk_size; - else request->content_length += chunk_size; + sprintfW( path, fmt, connect->hostname, connect->hostport ); + requestString = build_header_request_string( request, verbConnect, + path, http1_1 ); + heap_free( path ); + if (requestString) + { + LPSTR req_ascii = strdupWA( requestString ); - request->read_chunked_size = chunk_size; - if (!chunk_size) request->read_chunked_eof = TRUE; + heap_free( requestString ); + if (req_ascii) + { + int len = strlen( req_ascii ), bytes_sent; - return discard_eol( request, notify ); + ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent ); + heap_free( req_ascii ); + if (ret) + ret = read_reply( request ); } - remove_data( request, 1 ); - } - if (!read_more_data( request, -1, notify )) return FALSE; - if (!request->read_size) - { - request->content_length = request->content_read = 0; - request->read_chunked_size = 0; - return TRUE; } } + return ret; } -static BOOL refill_buffer( request_t *request, BOOL notify ) +#ifndef INET6_ADDRSTRLEN +#define INET6_ADDRSTRLEN 46 +#endif + +static WCHAR *addr_to_str( struct sockaddr_storage *addr ) { - int len = sizeof(request->read_buf); + char buf[INET6_ADDRSTRLEN]; + void *src; - if (request->read_chunked) - { - if (request->read_chunked_eof) return FALSE; - if (request->read_chunked_size == ~0u || !request->read_chunked_size) - { - if (!start_next_chunk( request, notify )) return FALSE; - } - len = min( len, request->read_chunked_size ); - } - else if (request->content_length != ~0u) + switch (addr->ss_family) { - len = min( len, request->content_length - request->content_read ); + case AF_INET: + src = &((struct sockaddr_in *)addr)->sin_addr; + break; + case AF_INET6: + src = &((struct sockaddr_in6 *)addr)->sin6_addr; + break; + default: + WARN("unsupported address family %d\n", addr->ss_family); + return NULL; } - - if (len <= request->read_size) return TRUE; - if (!read_more_data( request, len, notify )) return FALSE; - if (!request->read_size) request->content_length = request->content_read = 0; - return TRUE; + if (!inet_ntop( addr->ss_family, src, buf, sizeof(buf) )) return NULL; + return strdupAW( buf ); } -static void finished_reading( request_t *request ) +static CRITICAL_SECTION connection_pool_cs; +static CRITICAL_SECTION_DEBUG connection_pool_debug = { - static const WCHAR closeW[] = {'c','l','o','s','e',0}; + 0, 0, &connection_pool_cs, + { &connection_pool_debug.ProcessLocksList, &connection_pool_debug.ProcessLocksList }, + 0, 0, { (DWORD_PTR)(__FILE__ ": connection_pool_cs") } +}; +static CRITICAL_SECTION connection_pool_cs = { &connection_pool_debug, -1, 0, 0, 0, 0 }; - BOOL close = FALSE; - WCHAR connection[20]; - DWORD size = sizeof(connection); +static struct list connection_pool = LIST_INIT( connection_pool ); - if (!request->netconn) return; +void release_host( hostdata_t *host ) +{ + LONG ref; - if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE; - else if (query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) || - query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection, &size, NULL )) - { - if (!strcmpiW( connection, closeW )) close = TRUE; - } - else if (!strcmpW( request->version, http1_0 )) close = TRUE; - if (close) - { - close_connection( request ); - return; - } + EnterCriticalSection( &connection_pool_cs ); + if (!(ref = --host->ref)) list_remove( &host->entry ); + LeaveCriticalSection( &connection_pool_cs ); + if (ref) return; - cache_connection( request->netconn ); - request->netconn = NULL; + assert( list_empty( &host->connections ) ); + heap_free( host->hostname ); + heap_free( host ); } -/* return the size of data available to be read immediately */ -static DWORD get_available_data( request_t *request ) -{ - if (request->read_chunked) return min( request->read_chunked_size, request->read_size ); - return request->read_size; -} +static BOOL connection_collector_running; -/* check if we have reached the end of the data to read */ -static BOOL end_of_read_data( request_t *request ) +static DWORD WINAPI connection_collector(void *arg) { - if (!request->content_length) return TRUE; - if (request->read_chunked) return request->read_chunked_eof; - if (request->content_length == ~0u) return FALSE; - return (request->content_length == request->content_read); -} + unsigned int remaining_connections; + netconn_t *netconn, *next_netconn; + hostdata_t *host, *next_host; + ULONGLONG now; -static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async ) -{ - int count, bytes_read = 0; + do + { + /* FIXME: Use more sophisticated method */ + Sleep(5000); + remaining_connections = 0; + now = GetTickCount64(); - if (end_of_read_data( request )) goto done; + EnterCriticalSection(&connection_pool_cs); - while (size) - { - if (!(count = get_available_data( request ))) + LIST_FOR_EACH_ENTRY_SAFE(host, next_host, &connection_pool, hostdata_t, entry) { - if (!refill_buffer( request, async )) goto done; - if (!(count = get_available_data( request ))) goto done; - } - count = min( count, size ); - memcpy( (char *)buffer + bytes_read, request->read_buf + request->read_pos, count ); - remove_data( request, count ); - if (request->read_chunked) request->read_chunked_size -= count; - size -= count; - bytes_read += count; - request->content_read += count; - if (end_of_read_data( request )) goto done; - } - if (request->read_chunked && !request->read_chunked_size) refill_buffer( request, async ); + LIST_FOR_EACH_ENTRY_SAFE(netconn, next_netconn, &host->connections, netconn_t, entry) + { + if (netconn->keep_until < now) + { + TRACE("freeing %p\n", netconn); + list_remove(&netconn->entry); + netconn_close(netconn); + } + else + { + remaining_connections++; + } + } + } -done: - TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, request->content_read, request->content_length ); + if (!remaining_connections) connection_collector_running = FALSE; - if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read ); - if (read) *read = bytes_read; - if (end_of_read_data( request )) finished_reading( request ); - return TRUE; + LeaveCriticalSection(&connection_pool_cs); + } while(remaining_connections); + + FreeLibraryAndExitThread( winhttp_instance, 0 ); } -/* read any content returned by the server so that the connection can be reused */ -static void drain_content( request_t *request ) +static void cache_connection( netconn_t *netconn ) { - DWORD size, bytes_read, bytes_total = 0, bytes_left = request->content_length - request->content_read; - char buffer[2048]; + TRACE( "caching connection %p\n", netconn ); - refill_buffer( request, FALSE ); - for (;;) + EnterCriticalSection( &connection_pool_cs ); + + netconn->keep_until = GetTickCount64() + DEFAULT_KEEP_ALIVE_TIMEOUT; + list_add_head( &netconn->host->connections, &netconn->entry ); + + if (!connection_collector_running) { - if (request->read_chunked) size = sizeof(buffer); + HMODULE module; + HANDLE thread; + + GetModuleHandleExW( GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS, (const WCHAR*)winhttp_instance, &module ); + + thread = CreateThread(NULL, 0, connection_collector, NULL, 0, NULL); + if (thread) + { + CloseHandle( thread ); + connection_collector_running = TRUE; + } else { - if (bytes_total >= bytes_left) return; - size = min( sizeof(buffer), bytes_left - bytes_total ); + FreeLibrary( winhttp_instance ); } - if (!read_data( request, buffer, size, &bytes_read, FALSE ) || !bytes_read) return; - bytes_total += bytes_read; } + + LeaveCriticalSection( &connection_pool_cs ); } -static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len, LPVOID optional, - DWORD optional_len, DWORD total_len, DWORD_PTR context, BOOL async ) +static DWORD map_secure_protocols( DWORD mask ) { - static const WCHAR keep_alive[] = {'K','e','e','p','-','A','l','i','v','e',0}; - static const WCHAR no_cache[] = {'n','o','-','c','a','c','h','e',0}; - static const WCHAR length_fmt[] = {'%','l','d',0}; - - BOOL ret = FALSE; - connect_t *connect = request->connect; - session_t *session = connect->session; - WCHAR *req = NULL; - char *req_ascii; - int bytes_sent; - DWORD len; - - clear_response_headers( request ); - drain_content( request ); + DWORD ret = 0; + if (mask & WINHTTP_FLAG_SECURE_PROTOCOL_SSL2) ret |= SP_PROT_SSL2_CLIENT; + if (mask & WINHTTP_FLAG_SECURE_PROTOCOL_SSL3) ret |= SP_PROT_SSL3_CLIENT; + if (mask & WINHTTP_FLAG_SECURE_PROTOCOL_TLS1) ret |= SP_PROT_TLS1_CLIENT; + if (mask & WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1) ret |= SP_PROT_TLS1_1_CLIENT; + if (mask & WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2) ret |= SP_PROT_TLS1_2_CLIENT; + return ret; +} - if (session->agent) - process_header( request, attr_user_agent, session->agent, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); +static BOOL ensure_cred_handle( session_t *session ) +{ + SCHANNEL_CRED cred; + SECURITY_STATUS status; - if (connect->hostname) - add_host_header( request, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW ); + if (session->cred_handle_initialized) return TRUE; - if (total_len || (request->verb && !strcmpW( request->verb, postW ))) - { - WCHAR length[21]; /* decimal long int + null */ - sprintfW( length, length_fmt, total_len ); - process_header( request, attr_content_length, length, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); - } - if (!(request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE)) - { - process_header( request, attr_connection, keep_alive, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); - } - if (request->hdr.flags & WINHTTP_FLAG_REFRESH) - { - process_header( request, attr_pragma, no_cache, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); - process_header( request, attr_cache_control, no_cache, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); - } - if (headers && !add_request_headers( request, headers, headers_len, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE )) + memset( &cred, 0, sizeof(cred) ); + cred.dwVersion = SCHANNEL_CRED_VERSION; + cred.grbitEnabledProtocols = map_secure_protocols( session->secure_protocols ); + if ((status = AcquireCredentialsHandleW( NULL, (WCHAR *)UNISP_NAME_W, SECPKG_CRED_OUTBOUND, NULL, &cred, + NULL, NULL, &session->cred_handle, NULL )) != SEC_E_OK) { - TRACE("failed to add request headers\n"); - return FALSE; - } - if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES) && !add_cookie_headers( request )) - { - WARN("failed to add cookie headers\n"); + WARN( "AcquireCredentialsHandleW failed: 0x%08x\n", status ); return FALSE; } + session->cred_handle_initialized = TRUE; + return TRUE; +} - if (context) request->hdr.context = context; - - if (!(ret = open_connection( request ))) goto end; - if (!(req = build_request_string( request ))) goto end; +static BOOL open_connection( request_t *request ) +{ + BOOL is_secure = request->hdr.flags & WINHTTP_FLAG_SECURE; + hostdata_t *host = NULL, *iter; + netconn_t *netconn = NULL; + connect_t *connect; + WCHAR *addressW = NULL; + INTERNET_PORT port; + DWORD len; - if (!(req_ascii = strdupWA( req ))) goto end; - TRACE("full request: %s\n", debugstr_a(req_ascii)); - len = strlen(req_ascii); + if (request->netconn) goto done; - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0 ); + connect = request->connect; + port = connect->serverport ? connect->serverport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80); - ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent ); - heap_free( req_ascii ); - if (!ret) goto end; + EnterCriticalSection( &connection_pool_cs ); - if (optional_len) + LIST_FOR_EACH_ENTRY( iter, &connection_pool, hostdata_t, entry ) { - if (!netconn_send( request->netconn, optional, optional_len, &bytes_sent )) goto end; - request->optional = optional; - request->optional_len = optional_len; - len += optional_len; + if (iter->port == port && !strcmpW( connect->servername, iter->hostname ) && !is_secure == !iter->secure) + { + host = iter; + host->ref++; + break; + } } - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, &len, sizeof(len) ); -end: - if (async) + if (!host) { - if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NULL, 0 ); - else + if ((host = heap_alloc( sizeof(*host) ))) { - WINHTTP_ASYNC_RESULT result; - result.dwResult = API_SEND_REQUEST; - result.dwError = get_last_error(); - send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); + host->ref = 1; + host->secure = is_secure; + host->port = port; + list_init( &host->connections ); + if ((host->hostname = strdupW( connect->servername ))) + { + list_add_head( &connection_pool, &host->entry ); + } + else + { + heap_free( host ); + host = NULL; + } } } - heap_free( req ); - return ret; -} - -static void task_send_request( task_header_t *task ) -{ - send_request_t *s = (send_request_t *)task; - send_request( s->hdr.request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE ); - heap_free( s->headers ); -} -/*********************************************************************** - * WinHttpSendRequest (winhttp.@) - */ -BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD headers_len, - LPVOID optional, DWORD optional_len, DWORD total_len, DWORD_PTR context ) -{ - BOOL ret; - request_t *request; + LeaveCriticalSection( &connection_pool_cs ); - TRACE("%p, %s, 0x%x, %u, %u, %lx\n", - hrequest, debugstr_w(headers), headers_len, optional_len, total_len, context); + if (!host) return FALSE; - if (!(request = (request_t *)grab_object( hrequest ))) + for (;;) { - set_last_error( ERROR_INVALID_HANDLE ); - return FALSE; + EnterCriticalSection( &connection_pool_cs ); + if (!list_empty( &host->connections )) + { + netconn = LIST_ENTRY( list_head( &host->connections ), netconn_t, entry ); + list_remove( &netconn->entry ); + } + LeaveCriticalSection( &connection_pool_cs ); + if (!netconn) break; + + if (netconn_is_alive( netconn )) break; + TRACE("connection %p no longer alive, closing\n", netconn); + netconn_close( netconn ); + netconn = NULL; } - if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) + + if (!connect->resolved && netconn) { - release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); - return FALSE; + connect->sockaddr = netconn->sockaddr; + connect->resolved = TRUE; } - if (headers && !headers_len) headers_len = strlenW( headers ); - - if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) + if (!connect->resolved) { - send_request_t *s; + len = strlenW( host->hostname ) + 1; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESOLVING_NAME, host->hostname, len ); - if (!(s = heap_alloc( sizeof(send_request_t) ))) return FALSE; - s->hdr.request = request; - s->hdr.proc = task_send_request; - s->headers = strdupW( headers ); - s->headers_len = headers_len; - s->optional = optional; - s->optional_len = optional_len; - s->total_len = total_len; - s->context = context; + if (!netconn_resolve( host->hostname, port, &connect->sockaddr, request->resolve_timeout )) + { + release_host( host ); + return FALSE; + } + connect->resolved = TRUE; - addref_object( &request->hdr ); - ret = queue_task( (task_header_t *)s ); + if (!(addressW = addr_to_str( &connect->sockaddr ))) + { + release_host( host ); + return FALSE; + } + len = strlenW( addressW ) + 1; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_NAME_RESOLVED, addressW, len ); } - else - ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context, FALSE ); - - release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); - return ret; -} -#undef ARRAYSIZE -#define ARRAYSIZE(array) (sizeof(array) / sizeof((array)[0])) + if (!netconn) + { + if (!addressW && !(addressW = addr_to_str( &connect->sockaddr ))) + { + release_host( host ); + return FALSE; + } -static const WCHAR basicW[] = {'B','a','s','i','c',0}; -static const WCHAR ntlmW[] = {'N','T','L','M',0}; -static const WCHAR passportW[] = {'P','a','s','s','p','o','r','t',0}; -static const WCHAR digestW[] = {'D','i','g','e','s','t',0}; -static const WCHAR negotiateW[] = {'N','e','g','o','t','i','a','t','e',0}; + TRACE("connecting to %s:%u\n", debugstr_w(addressW), port); -static const struct -{ - const WCHAR *str; - unsigned int len; - DWORD scheme; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTING_TO_SERVER, addressW, 0 ); + + if (!(netconn = netconn_create( host, &connect->sockaddr, request->connect_timeout ))) + { + heap_free( addressW ); + release_host( host ); + return FALSE; + } + netconn_set_timeout( netconn, TRUE, request->send_timeout ); + netconn_set_timeout( netconn, FALSE, request->recv_timeout ); + if (is_secure) + { + if (connect->session->proxy_server && + strcmpiW( connect->hostname, connect->servername )) + { + if (!secure_proxy_connect( request )) + { + heap_free( addressW ); + netconn_close( netconn ); + return FALSE; + } + } + if (!ensure_cred_handle( connect->session ) || + !netconn_secure_connect( netconn, connect->hostname, request->security_flags, + &connect->session->cred_handle )) + { + heap_free( addressW ); + netconn_close( netconn ); + return FALSE; + } + } + + request->netconn = netconn; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTED_TO_SERVER, addressW, strlenW(addressW) + 1 ); + } + else + { + TRACE("using connection %p\n", netconn); + + netconn_set_timeout( netconn, TRUE, request->send_timeout ); + netconn_set_timeout( netconn, FALSE, request->recv_timeout ); + request->netconn = netconn; + } + +done: + request->read_pos = request->read_size = 0; + request->read_chunked = FALSE; + request->read_chunked_size = ~0u; + request->read_chunked_eof = FALSE; + heap_free( addressW ); + return TRUE; } -auth_schemes[] = -{ - { basicW, ARRAYSIZE(basicW) - 1, WINHTTP_AUTH_SCHEME_BASIC }, - { ntlmW, ARRAYSIZE(ntlmW) - 1, WINHTTP_AUTH_SCHEME_NTLM }, - { passportW, ARRAYSIZE(passportW) - 1, WINHTTP_AUTH_SCHEME_PASSPORT }, - { digestW, ARRAYSIZE(digestW) - 1, WINHTTP_AUTH_SCHEME_DIGEST }, - { negotiateW, ARRAYSIZE(negotiateW) - 1, WINHTTP_AUTH_SCHEME_NEGOTIATE } -}; -static const unsigned int num_auth_schemes = sizeof(auth_schemes)/sizeof(auth_schemes[0]); -static enum auth_scheme scheme_from_flag( DWORD flag ) +void close_connection( request_t *request ) { - int i; + if (!request->netconn) return; - for (i = 0; i < num_auth_schemes; i++) if (flag == auth_schemes[i].scheme) return i; - return SCHEME_INVALID; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CLOSING_CONNECTION, 0, 0 ); + netconn_close( request->netconn ); + request->netconn = NULL; + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_CONNECTION_CLOSED, 0, 0 ); } -static DWORD auth_scheme_from_header( WCHAR *header ) +static BOOL add_host_header( request_t *request, DWORD modifier ) { - unsigned int i; + BOOL ret; + DWORD len; + WCHAR *host; + static const WCHAR fmt[] = {'%','s',':','%','u',0}; + connect_t *connect = request->connect; + INTERNET_PORT port; - for (i = 0; i < num_auth_schemes; i++) + port = connect->hostport ? connect->hostport : (request->hdr.flags & WINHTTP_FLAG_SECURE ? 443 : 80); + + if (port == INTERNET_DEFAULT_HTTP_PORT || port == INTERNET_DEFAULT_HTTPS_PORT) { - if (!strncmpiW( header, auth_schemes[i].str, auth_schemes[i].len ) && - (header[auth_schemes[i].len] == ' ' || !header[auth_schemes[i].len])) return auth_schemes[i].scheme; + return process_header( request, attr_host, connect->hostname, modifier, TRUE ); } - return 0; + len = strlenW( connect->hostname ) + 7; /* sizeof(":65335") */ + if (!(host = heap_alloc( len * sizeof(WCHAR) ))) return FALSE; + sprintfW( host, fmt, connect->hostname, port ); + ret = process_header( request, attr_host, host, modifier, TRUE ); + heap_free( host ); + return ret; } -static BOOL query_auth_schemes( request_t *request, DWORD level, LPDWORD supported, LPDWORD first ) +static void clear_response_headers( request_t *request ) { - DWORD index = 0, supported_schemes = 0, first_scheme = 0; - BOOL ret = FALSE; + unsigned int i; - for (;;) + for (i = 0; i < request->num_headers; i++) { - WCHAR *buffer; - DWORD size, scheme; - - size = 0; - query_headers( request, level, NULL, NULL, &size, &index ); - if (get_last_error() != ERROR_INSUFFICIENT_BUFFER) break; - - index--; - if (!(buffer = heap_alloc( size ))) return FALSE; - if (!query_headers( request, level, NULL, buffer, &size, &index )) - { - heap_free( buffer ); - return FALSE; - } - scheme = auth_scheme_from_header( buffer ); - heap_free( buffer ); - if (!scheme) continue; - - if (!first_scheme) first_scheme = scheme; - supported_schemes |= scheme; - - ret = TRUE; + if (!request->headers[i].field) continue; + if (!request->headers[i].value) continue; + if (request->headers[i].is_request) continue; + delete_header( request, i ); + i--; } +} - if (ret) - { - *supported = supported_schemes; - *first = first_scheme; - } - return ret; +/* remove some amount of data from the read buffer */ +static void remove_data( request_t *request, int count ) +{ + if (!(request->read_size -= count)) request->read_pos = 0; + else request->read_pos += count; } -/*********************************************************************** - * WinHttpQueryAuthSchemes (winhttp.@) - */ -BOOL WINAPI WinHttpQueryAuthSchemes( HINTERNET hrequest, LPDWORD supported, LPDWORD first, LPDWORD target ) +/* read some more data into the read buffer */ +static BOOL read_more_data( request_t *request, int maxlen, BOOL notify ) { - BOOL ret = FALSE; - request_t *request; + int len; + BOOL ret; - TRACE("%p, %p, %p, %p\n", hrequest, supported, first, target); + if (request->read_chunked_eof) return FALSE; - if (!(request = (request_t *)grab_object( hrequest ))) - { - set_last_error( ERROR_INVALID_HANDLE ); - return FALSE; - } - if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) + if (request->read_size && request->read_pos) { - release_object( &request->hdr ); - set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); - return FALSE; + /* move existing data to the start of the buffer */ + memmove( request->read_buf, request->read_buf + request->read_pos, request->read_size ); + request->read_pos = 0; } - if (!supported || !first || !target) - { - release_object( &request->hdr ); - set_last_error( ERROR_INVALID_PARAMETER ); - return FALSE; + if (maxlen == -1) maxlen = sizeof(request->read_buf); - } + if (notify) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RECEIVING_RESPONSE, NULL, 0 ); - if (query_auth_schemes( request, WINHTTP_QUERY_WWW_AUTHENTICATE, supported, first )) - { - *target = WINHTTP_AUTH_TARGET_SERVER; - ret = TRUE; - } - else if (query_auth_schemes( request, WINHTTP_QUERY_PROXY_AUTHENTICATE, supported, first )) - { - *target = WINHTTP_AUTH_TARGET_PROXY; - ret = TRUE; - } + ret = netconn_recv( request->netconn, request->read_buf + request->read_size, + maxlen - request->read_size, 0, &len ); - release_object( &request->hdr ); - if (ret) set_last_error( ERROR_SUCCESS ); + if (notify) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_RESPONSE_RECEIVED, &len, sizeof(len) ); + + request->read_size += len; return ret; } -static UINT encode_base64( const char *bin, unsigned int len, WCHAR *base64 ) +/* discard data contents until we reach end of line */ +static BOOL discard_eol( request_t *request, BOOL notify ) { - UINT n = 0, x; - static const char base64enc[] = - "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"; - - while (len > 0) + do { - /* first 6 bits, all from bin[0] */ - base64[n++] = base64enc[(bin[0] & 0xfc) >> 2]; - x = (bin[0] & 3) << 4; - - /* next 6 bits, 2 from bin[0] and 4 from bin[1] */ - if (len == 1) - { - base64[n++] = base64enc[x]; - base64[n++] = '='; - base64[n++] = '='; - break; - } - base64[n++] = base64enc[x | ((bin[1] & 0xf0) >> 4)]; - x = (bin[1] & 0x0f) << 2; - - /* next 6 bits 4 from bin[1] and 2 from bin[2] */ - if (len == 2) + char *eol = memchr( request->read_buf + request->read_pos, '\n', request->read_size ); + if (eol) { - base64[n++] = base64enc[x]; - base64[n++] = '='; + remove_data( request, (eol + 1) - (request->read_buf + request->read_pos) ); break; } - base64[n++] = base64enc[x | ((bin[2] & 0xc0) >> 6)]; - - /* last 6 bits, all from bin [2] */ - base64[n++] = base64enc[bin[2] & 0x3f]; - bin += 3; - len -= 3; - } - base64[n] = 0; - return n; + request->read_pos = request->read_size = 0; /* discard everything */ + if (!read_more_data( request, -1, notify )) return FALSE; + } while (request->read_size); + return TRUE; } -static inline char decode_char( WCHAR c ) +/* read the size of the next chunk */ +static BOOL start_next_chunk( request_t *request, BOOL notify ) { - if (c >= 'A' && c <= 'Z') return c - 'A'; - if (c >= 'a' && c <= 'z') return c - 'a' + 26; - if (c >= '0' && c <= '9') return c - '0' + 52; - if (c == '+') return 62; - if (c == '/') return 63; - return 64; -} + DWORD chunk_size = 0; -static unsigned int decode_base64( const WCHAR *base64, unsigned int len, char *buf ) -{ - unsigned int i = 0; - char c0, c1, c2, c3; - const WCHAR *p = base64; + assert(!request->read_chunked_size || request->read_chunked_size == ~0u); - while (len > 4) + if (request->read_chunked_eof) return FALSE; + + /* read terminator for the previous chunk */ + if (!request->read_chunked_size && !discard_eol( request, notify )) return FALSE; + + for (;;) { - if ((c0 = decode_char( p[0] )) > 63) return 0; - if ((c1 = decode_char( p[1] )) > 63) return 0; - if ((c2 = decode_char( p[2] )) > 63) return 0; - if ((c3 = decode_char( p[3] )) > 63) return 0; + while (request->read_size) + { + char ch = request->read_buf[request->read_pos]; + if (ch >= '0' && ch <= '9') chunk_size = chunk_size * 16 + ch - '0'; + else if (ch >= 'a' && ch <= 'f') chunk_size = chunk_size * 16 + ch - 'a' + 10; + else if (ch >= 'A' && ch <= 'F') chunk_size = chunk_size * 16 + ch - 'A' + 10; + else if (ch == ';' || ch == '\r' || ch == '\n') + { + TRACE("reading %u byte chunk\n", chunk_size); - if (buf) + if (request->content_length == ~0u) request->content_length = chunk_size; + else request->content_length += chunk_size; + + request->read_chunked_size = chunk_size; + if (!chunk_size) request->read_chunked_eof = TRUE; + + return discard_eol( request, notify ); + } + remove_data( request, 1 ); + } + if (!read_more_data( request, -1, notify )) return FALSE; + if (!request->read_size) { - buf[i + 0] = (c0 << 2) | (c1 >> 4); - buf[i + 1] = (c1 << 4) | (c2 >> 2); - buf[i + 2] = (c2 << 6) | c3; + request->content_length = request->content_read = 0; + request->read_chunked_size = 0; + return TRUE; } - len -= 4; - i += 3; - p += 4; } - if (p[2] == '=') - { - if ((c0 = decode_char( p[0] )) > 63) return 0; - if ((c1 = decode_char( p[1] )) > 63) return 0; +} - if (buf) buf[i] = (c0 << 2) | (c1 >> 4); - i++; - } - else if (p[3] == '=') - { - if ((c0 = decode_char( p[0] )) > 63) return 0; - if ((c1 = decode_char( p[1] )) > 63) return 0; - if ((c2 = decode_char( p[2] )) > 63) return 0; +static BOOL refill_buffer( request_t *request, BOOL notify ) +{ + int len = sizeof(request->read_buf); - if (buf) + if (request->read_chunked) + { + if (request->read_chunked_eof) return FALSE; + if (request->read_chunked_size == ~0u || !request->read_chunked_size) { - buf[i + 0] = (c0 << 2) | (c1 >> 4); - buf[i + 1] = (c1 << 4) | (c2 >> 2); + if (!start_next_chunk( request, notify )) return FALSE; } - i += 2; + len = min( len, request->read_chunked_size ); } - else + else if (request->content_length != ~0u) { - if ((c0 = decode_char( p[0] )) > 63) return 0; - if ((c1 = decode_char( p[1] )) > 63) return 0; - if ((c2 = decode_char( p[2] )) > 63) return 0; - if ((c3 = decode_char( p[3] )) > 63) return 0; - - if (buf) - { - buf[i + 0] = (c0 << 2) | (c1 >> 4); - buf[i + 1] = (c1 << 4) | (c2 >> 2); - buf[i + 2] = (c2 << 6) | c3; - } - i += 3; + len = min( len, request->content_length - request->content_read ); } - return i; + + if (len <= request->read_size) return TRUE; + if (!read_more_data( request, len, notify )) return FALSE; + if (!request->read_size) request->content_length = request->content_read = 0; + return TRUE; } -static struct authinfo *alloc_authinfo(void) +static void finished_reading( request_t *request ) { - struct authinfo *ret; + static const WCHAR closeW[] = {'c','l','o','s','e',0}; - if (!(ret = heap_alloc( sizeof(*ret) ))) return NULL; + BOOL close = FALSE; + WCHAR connection[20]; + DWORD size = sizeof(connection); - SecInvalidateHandle( &ret->cred ); - SecInvalidateHandle( &ret->ctx ); - memset( &ret->exp, 0, sizeof(ret->exp) ); - ret->scheme = 0; - ret->attr = 0; - ret->max_token = 0; - ret->data = NULL; - ret->data_len = 0; - ret->finished = FALSE; - return ret; -} + if (!request->netconn) return; -void destroy_authinfo( struct authinfo *authinfo ) -{ - if (!authinfo) return; + if (request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE) close = TRUE; + else if (query_headers( request, WINHTTP_QUERY_CONNECTION, NULL, connection, &size, NULL ) || + query_headers( request, WINHTTP_QUERY_PROXY_CONNECTION, NULL, connection, &size, NULL )) + { + if (!strcmpiW( connection, closeW )) close = TRUE; + } + else if (!strcmpW( request->version, http1_0 )) close = TRUE; + if (close) + { + close_connection( request ); + return; + } - if (SecIsValidHandle( &authinfo->ctx )) - DeleteSecurityContext( &authinfo->ctx ); - if (SecIsValidHandle( &authinfo->cred )) - FreeCredentialsHandle( &authinfo->cred ); + cache_connection( request->netconn ); + request->netconn = NULL; +} - heap_free( authinfo->data ); - heap_free( authinfo ); +/* return the size of data available to be read immediately */ +static DWORD get_available_data( request_t *request ) +{ + if (request->read_chunked) return min( request->read_chunked_size, request->read_size ); + return request->read_size; } -static BOOL get_authvalue( request_t *request, DWORD level, DWORD scheme, WCHAR *buffer, DWORD len ) +/* check if we have reached the end of the data to read */ +static BOOL end_of_read_data( request_t *request ) { - DWORD size, index = 0; - for (;;) - { - size = len; - if (!query_headers( request, level, NULL, buffer, &size, &index )) return FALSE; - if (auth_scheme_from_header( buffer ) == scheme) break; - } - return TRUE; + if (!request->content_length) return TRUE; + if (request->read_chunked) return request->read_chunked_eof; + if (request->content_length == ~0u) return FALSE; + return (request->content_length == request->content_read); } -static BOOL do_authorization( request_t *request, DWORD target, DWORD scheme_flag ) +static BOOL read_data( request_t *request, void *buffer, DWORD size, DWORD *read, BOOL async ) { - struct authinfo *authinfo, **auth_ptr; - enum auth_scheme scheme = scheme_from_flag( scheme_flag ); - const WCHAR *auth_target, *username, *password; - WCHAR auth_value[2048], *auth_reply; - DWORD len = sizeof(auth_value), len_scheme, flags; - BOOL ret; + int count, bytes_read = 0; - if (scheme == SCHEME_INVALID) return FALSE; + if (end_of_read_data( request )) goto done; - switch (target) + while (size) { - case WINHTTP_AUTH_TARGET_SERVER: - if (!get_authvalue( request, WINHTTP_QUERY_WWW_AUTHENTICATE, scheme_flag, auth_value, len )) - return FALSE; - auth_ptr = &request->authinfo; - auth_target = attr_authorization; - if (request->creds[TARGET_SERVER][scheme].username) - { - username = request->creds[TARGET_SERVER][scheme].username; - password = request->creds[TARGET_SERVER][scheme].password; - } - else + if (!(count = get_available_data( request ))) { - username = request->connect->username; - password = request->connect->password; + if (!refill_buffer( request, async )) goto done; + if (!(count = get_available_data( request ))) goto done; } - break; + count = min( count, size ); + memcpy( (char *)buffer + bytes_read, request->read_buf + request->read_pos, count ); + remove_data( request, count ); + if (request->read_chunked) request->read_chunked_size -= count; + size -= count; + bytes_read += count; + request->content_read += count; + if (end_of_read_data( request )) goto done; + } + if (request->read_chunked && !request->read_chunked_size) refill_buffer( request, async ); - case WINHTTP_AUTH_TARGET_PROXY: - if (!get_authvalue( request, WINHTTP_QUERY_PROXY_AUTHENTICATE, scheme_flag, auth_value, len )) - return FALSE; - auth_ptr = &request->proxy_authinfo; - auth_target = attr_proxy_authorization; - if (request->creds[TARGET_PROXY][scheme].username) - { - username = request->creds[TARGET_PROXY][scheme].username; - password = request->creds[TARGET_PROXY][scheme].password; - } +done: + TRACE( "retrieved %u bytes (%u/%u)\n", bytes_read, request->content_read, request->content_length ); + + if (async) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_READ_COMPLETE, buffer, bytes_read ); + if (read) *read = bytes_read; + if (end_of_read_data( request )) finished_reading( request ); + return TRUE; +} + +/* read any content returned by the server so that the connection can be reused */ +static void drain_content( request_t *request ) +{ + DWORD size, bytes_read, bytes_total = 0, bytes_left = request->content_length - request->content_read; + char buffer[2048]; + + refill_buffer( request, FALSE ); + for (;;) + { + if (request->read_chunked) size = sizeof(buffer); else { - username = request->connect->session->proxy_username; - password = request->connect->session->proxy_password; + if (bytes_total >= bytes_left) return; + size = min( sizeof(buffer), bytes_left - bytes_total ); } - break; - - default: - WARN("unknown target %x\n", target); - return FALSE; + if (!read_data( request, buffer, size, &bytes_read, FALSE ) || !bytes_read) return; + bytes_total += bytes_read; } - authinfo = *auth_ptr; +} - switch (scheme) - { - case SCHEME_BASIC: - { - int userlen, passlen; +static BOOL send_request( request_t *request, LPCWSTR headers, DWORD headers_len, LPVOID optional, + DWORD optional_len, DWORD total_len, DWORD_PTR context, BOOL async ) +{ + static const WCHAR keep_alive[] = {'K','e','e','p','-','A','l','i','v','e',0}; + static const WCHAR no_cache[] = {'n','o','-','c','a','c','h','e',0}; + static const WCHAR length_fmt[] = {'%','l','d',0}; - if (!username || !password) return FALSE; - if ((!authinfo && !(authinfo = alloc_authinfo())) || authinfo->finished) return FALSE; + BOOL ret = FALSE; + connect_t *connect = request->connect; + session_t *session = connect->session; + WCHAR *req = NULL; + char *req_ascii; + int bytes_sent; + DWORD len, i, flags; - userlen = WideCharToMultiByte( CP_UTF8, 0, username, strlenW( username ), NULL, 0, NULL, NULL ); - passlen = WideCharToMultiByte( CP_UTF8, 0, password, strlenW( password ), NULL, 0, NULL, NULL ); + clear_response_headers( request ); + drain_content( request ); - authinfo->data_len = userlen + 1 + passlen; - if (!(authinfo->data = heap_alloc( authinfo->data_len ))) return FALSE; + flags = WINHTTP_ADDREQ_FLAG_ADD|WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA; + for (i = 0; i < request->num_accept_types; i++) + { + process_header( request, attr_accept, request->accept_types[i], flags, TRUE ); + } + if (session->agent) + process_header( request, attr_user_agent, session->agent, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); - WideCharToMultiByte( CP_UTF8, 0, username, -1, authinfo->data, userlen, NULL, NULL ); - authinfo->data[userlen] = ':'; - WideCharToMultiByte( CP_UTF8, 0, password, -1, authinfo->data + userlen + 1, passlen, NULL, NULL ); + if (connect->hostname) + add_host_header( request, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW ); - authinfo->scheme = SCHEME_BASIC; - authinfo->finished = TRUE; - break; + if (request->creds[TARGET_SERVER][SCHEME_BASIC].username) + do_authorization( request, WINHTTP_AUTH_TARGET_SERVER, WINHTTP_AUTH_SCHEME_BASIC ); + + if (total_len || (request->verb && !strcmpW( request->verb, postW ))) + { + WCHAR length[21]; /* decimal long int + null */ + sprintfW( length, length_fmt, total_len ); + process_header( request, attr_content_length, length, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); } - case SCHEME_NTLM: - case SCHEME_NEGOTIATE: + if (!(request->hdr.disable_flags & WINHTTP_DISABLE_KEEP_ALIVE)) { - SECURITY_STATUS status; - SecBufferDesc out_desc, in_desc; - SecBuffer out, in; - ULONG flags = ISC_REQ_CONNECTION|ISC_REQ_USE_DCE_STYLE|ISC_REQ_MUTUAL_AUTH|ISC_REQ_DELEGATE; - const WCHAR *p; - BOOL first = FALSE; + process_header( request, attr_connection, keep_alive, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); + } + if (request->hdr.flags & WINHTTP_FLAG_REFRESH) + { + process_header( request, attr_pragma, no_cache, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); + process_header( request, attr_cache_control, no_cache, WINHTTP_ADDREQ_FLAG_ADD_IF_NEW, TRUE ); + } + if (headers && !add_request_headers( request, headers, headers_len, WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE )) + { + TRACE("failed to add request headers\n"); + return FALSE; + } + if (!(request->hdr.disable_flags & WINHTTP_DISABLE_COOKIES) && !add_cookie_headers( request )) + { + WARN("failed to add cookie headers\n"); + return FALSE; + } - if (!authinfo) - { - TimeStamp exp; - SEC_WINNT_AUTH_IDENTITY_W id; - WCHAR *domain, *user; + if (context) request->hdr.context = context; - if (!username || !password || !(authinfo = alloc_authinfo())) return FALSE; + if (!(ret = open_connection( request ))) goto end; + if (!(req = build_request_string( request ))) goto end; - first = TRUE; - domain = (WCHAR *)username; - user = strchrW( username, '\\' ); + if (!(req_ascii = strdupWA( req ))) goto end; + TRACE("full request: %s\n", debugstr_a(req_ascii)); + len = strlen(req_ascii); - if (user) user++; - else - { - user = (WCHAR *)username; - domain = NULL; - } - id.Flags = SEC_WINNT_AUTH_IDENTITY_UNICODE; - id.User = user; - id.UserLength = strlenW( user ); - id.Domain = domain; - id.DomainLength = domain ? user - domain - 1 : 0; - id.Password = (WCHAR *)password; - id.PasswordLength = strlenW( password ); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDING_REQUEST, NULL, 0 ); - status = AcquireCredentialsHandleW( NULL, (SEC_WCHAR *)auth_schemes[scheme].str, - SECPKG_CRED_OUTBOUND, NULL, &id, NULL, NULL, - &authinfo->cred, &exp ); - if (status == SEC_E_OK) - { - PSecPkgInfoW info; - status = QuerySecurityPackageInfoW( (SEC_WCHAR *)auth_schemes[scheme].str, &info ); - if (status == SEC_E_OK) - { - authinfo->max_token = info->cbMaxToken; - FreeContextBuffer( info ); - } - } - if (status != SEC_E_OK) - { - WARN("AcquireCredentialsHandleW for scheme %s failed with error 0x%08x\n", - debugstr_w(auth_schemes[scheme].str), status); - heap_free( authinfo ); - return FALSE; - } - authinfo->scheme = scheme; - } - else if (authinfo->finished) return FALSE; + ret = netconn_send( request->netconn, req_ascii, len, &bytes_sent ); + heap_free( req_ascii ); + if (!ret) goto end; - if ((strlenW( auth_value ) < auth_schemes[authinfo->scheme].len || - strncmpiW( auth_value, auth_schemes[authinfo->scheme].str, auth_schemes[authinfo->scheme].len ))) + if (optional_len) + { + if (!netconn_send( request->netconn, optional, optional_len, &bytes_sent )) goto end; + request->optional = optional; + request->optional_len = optional_len; + len += optional_len; + } + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_SENT, &len, sizeof(len) ); + +end: + if (async) + { + if (ret) send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_SENDREQUEST_COMPLETE, NULL, 0 ); + else { - ERR("authentication scheme changed from %s to %s\n", - debugstr_w(auth_schemes[authinfo->scheme].str), debugstr_w(auth_value)); - destroy_authinfo( authinfo ); - *auth_ptr = NULL; - return FALSE; + WINHTTP_ASYNC_RESULT result; + result.dwResult = API_SEND_REQUEST; + result.dwError = get_last_error(); + send_callback( &request->hdr, WINHTTP_CALLBACK_STATUS_REQUEST_ERROR, &result, sizeof(result) ); } - in.BufferType = SECBUFFER_TOKEN; - in.cbBuffer = 0; - in.pvBuffer = NULL; + } + heap_free( req ); + return ret; +} - in_desc.ulVersion = 0; - in_desc.cBuffers = 1; - in_desc.pBuffers = ∈ +static void task_send_request( task_header_t *task ) +{ + send_request_t *s = (send_request_t *)task; + send_request( s->hdr.request, s->headers, s->headers_len, s->optional, s->optional_len, s->total_len, s->context, TRUE ); + heap_free( s->headers ); +} - p = auth_value + auth_schemes[scheme].len; - if (*p == ' ') - { - int len = strlenW( ++p ); - in.cbBuffer = decode_base64( p, len, NULL ); - if (!(in.pvBuffer = heap_alloc( in.cbBuffer ))) { - destroy_authinfo( authinfo ); - *auth_ptr = NULL; - return FALSE; - } - decode_base64( p, len, in.pvBuffer ); - } - out.BufferType = SECBUFFER_TOKEN; - out.cbBuffer = authinfo->max_token; - if (!(out.pvBuffer = heap_alloc( authinfo->max_token ))) - { - heap_free( in.pvBuffer ); - destroy_authinfo( authinfo ); - *auth_ptr = NULL; - return FALSE; - } - out_desc.ulVersion = 0; - out_desc.cBuffers = 1; - out_desc.pBuffers = &out; +/*********************************************************************** + * WinHttpSendRequest (winhttp.@) + */ +BOOL WINAPI WinHttpSendRequest( HINTERNET hrequest, LPCWSTR headers, DWORD headers_len, + LPVOID optional, DWORD optional_len, DWORD total_len, DWORD_PTR context ) +{ + BOOL ret; + request_t *request; - status = InitializeSecurityContextW( first ? &authinfo->cred : NULL, first ? NULL : &authinfo->ctx, - first ? request->connect->servername : NULL, flags, 0, - SECURITY_NETWORK_DREP, in.pvBuffer ? &in_desc : NULL, 0, - &authinfo->ctx, &out_desc, &authinfo->attr, &authinfo->exp ); - heap_free( in.pvBuffer ); - if (status == SEC_E_OK) - { - heap_free( authinfo->data ); - authinfo->data = out.pvBuffer; - authinfo->data_len = out.cbBuffer; - authinfo->finished = TRUE; - TRACE("sending last auth packet\n"); - } - else if (status == SEC_I_CONTINUE_NEEDED) - { - heap_free( authinfo->data ); - authinfo->data = out.pvBuffer; - authinfo->data_len = out.cbBuffer; - TRACE("sending next auth packet\n"); - } - else - { - ERR("InitializeSecurityContextW failed with error 0x%08x\n", status); - heap_free( out.pvBuffer ); - destroy_authinfo( authinfo ); - *auth_ptr = NULL; - return FALSE; - } - break; + TRACE("%p, %s, %u, %u, %u, %lx\n", hrequest, debugstr_wn(headers, headers_len), headers_len, optional_len, + total_len, context); + + if (!(request = (request_t *)grab_object( hrequest ))) + { + set_last_error( ERROR_INVALID_HANDLE ); + return FALSE; } - default: - ERR("invalid scheme %u\n", scheme); + if (request->hdr.type != WINHTTP_HANDLE_TYPE_REQUEST) + { + release_object( &request->hdr ); + set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; } - *auth_ptr = authinfo; - len_scheme = auth_schemes[authinfo->scheme].len; - len = len_scheme + 1 + ((authinfo->data_len + 2) * 4) / 3; - if (!(auth_reply = heap_alloc( (len + 1) * sizeof(WCHAR) ))) return FALSE; + if (headers && !headers_len) headers_len = strlenW( headers ); - memcpy( auth_reply, auth_schemes[authinfo->scheme].str, len_scheme * sizeof(WCHAR) ); - auth_reply[len_scheme] = ' '; - encode_base64( authinfo->data, authinfo->data_len, auth_reply + len_scheme + 1 ); + if (request->connect->hdr.flags & WINHTTP_FLAG_ASYNC) + { + send_request_t *s; - flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_REPLACE; - ret = process_header( request, auth_target, auth_reply, flags, TRUE ); - heap_free( auth_reply ); + if (!(s = heap_alloc( sizeof(send_request_t) ))) return FALSE; + s->hdr.request = request; + s->hdr.proc = task_send_request; + s->headers = strdupW( headers ); + s->headers_len = headers_len; + s->optional = optional; + s->optional_len = optional_len; + s->total_len = total_len; + s->context = context; + + addref_object( &request->hdr ); + ret = queue_task( (task_header_t *)s ); + } + else + ret = send_request( request, headers, headers_len, optional, optional_len, total_len, context, FALSE ); + + release_object( &request->hdr ); + if (ret) set_last_error( ERROR_SUCCESS ); return ret; } diff --git a/dll/win32/winhttp/session.c b/dll/win32/winhttp/session.c index 429f505914..7ab10a66e4 100644 --- a/dll/win32/winhttp/session.c +++ b/dll/win32/winhttp/session.c @@ -71,6 +71,7 @@ static void session_destroy( object_header_t *hdr ) TRACE("%p\n", session); if (session->unload_event) SetEvent( session->unload_event ); + if (session->cred_handle_initialized) FreeCredentialsHandle( &session->cred_handle ); LIST_FOR_EACH_SAFE( item, next, &session->cookie_cache ) { @@ -155,6 +156,17 @@ static BOOL session_set_option( object_header_t *hdr, DWORD option, LPVOID buffe hdr->redirect_policy = policy; return TRUE; } + case WINHTTP_OPTION_SECURE_PROTOCOLS: + { + if (buflen != sizeof(session->secure_protocols)) + { + set_last_error( ERROR_INSUFFICIENT_BUFFER ); + return FALSE; + } + session->secure_protocols = *(DWORD *)buffer; + TRACE("0x%x\n", session->secure_protocols); + return TRUE; + } case WINHTTP_OPTION_DISABLE_FEATURE: set_last_error( ERROR_WINHTTP_INCORRECT_HANDLE_TYPE ); return FALSE; @@ -577,6 +589,8 @@ static void request_destroy( object_header_t *hdr ) heap_free( request->headers[i].value ); } heap_free( request->headers ); + for (i = 0; i < request->num_accept_types; i++) heap_free( request->accept_types[i] ); + heap_free( request->accept_types ); for (i = 0; i < TARGET_MAX; i++) { for (j = 0; j < SCHEME_MAX; j++) @@ -1002,14 +1016,32 @@ static const object_vtbl_t request_vtbl = static BOOL store_accept_types( request_t *request, const WCHAR **accept_types ) { - static const WCHAR attr_accept[] = {'A','c','c','e','p','t',0}; - static const DWORD flags = WINHTTP_ADDREQ_FLAG_ADD | WINHTTP_ADDREQ_FLAG_COALESCE_WITH_COMMA; const WCHAR **types = accept_types; + DWORD i; if (!types) return TRUE; while (*types) { - process_header( request, attr_accept, *types, flags, TRUE ); + request->num_accept_types++; + types++; + } + if (!request->num_accept_types) return TRUE; + if (!(request->accept_types = heap_alloc( request->num_accept_types * sizeof(WCHAR *)))) + { + request->num_accept_types = 0; + return FALSE; + } + types = accept_types; + for (i = 0; i < request->num_accept_types; i++) + { + if (!(request->accept_types[i] = strdupW( *types ))) + { + for ( ; i > 0; --i) heap_free( request->accept_types[i - 1] ); + heap_free( request->accept_types ); + request->accept_types = NULL; + request->num_accept_types = 0; + return FALSE; + } types++; } return TRUE; diff --git a/dll/win32/winhttp/winhttp_private.h b/dll/win32/winhttp/winhttp_private.h index 7e80dcab4e..1e6d16a238 100644 --- a/dll/win32/winhttp/winhttp_private.h +++ b/dll/win32/winhttp/winhttp_private.h @@ -135,6 +135,9 @@ typedef struct LPWSTR proxy_password; struct list cookie_cache; HANDLE unload_event; + CredHandle cred_handle; + BOOL cred_handle_initialized; + DWORD secure_protocols; } session_t; typedef struct @@ -235,6 +238,8 @@ typedef struct char read_buf[8192]; /* buffer for already read but not returned data */ header_t *headers; DWORD num_headers; + WCHAR **accept_types; + DWORD num_accept_types; struct authinfo *authinfo; struct authinfo *proxy_authinfo; HANDLE task_wait; @@ -313,7 +318,7 @@ void netconn_unload( void ) DECLSPEC_HIDDEN; ULONG netconn_query_data_available( netconn_t * ) DECLSPEC_HIDDEN; BOOL netconn_recv( netconn_t *, void *, size_t, int, int * ) DECLSPEC_HIDDEN; BOOL netconn_resolve( WCHAR *, INTERNET_PORT, struct sockaddr_storage *, int ) DECLSPEC_HIDDEN; -BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD ) DECLSPEC_HIDDEN; +BOOL netconn_secure_connect( netconn_t *, WCHAR *, DWORD, CredHandle * ) DECLSPEC_HIDDEN; BOOL netconn_send( netconn_t *, const void *, size_t, int * ) DECLSPEC_HIDDEN; DWORD netconn_set_timeout( netconn_t *, BOOL, int ) DECLSPEC_HIDDEN; BOOL netconn_is_alive( netconn_t * ) DECLSPEC_HIDDEN; @@ -329,8 +334,6 @@ void destroy_authinfo( struct authinfo * ) DECLSPEC_HIDDEN; void release_host( hostdata_t *host ) DECLSPEC_HIDDEN; -BOOL process_header( request_t *request, LPCWSTR field, LPCWSTR value, DWORD flags, BOOL request_only ) DECLSPEC_HIDDEN; - extern HRESULT WinHttpRequest_create( void ** ) DECLSPEC_HIDDEN; void release_typelib( void ) DECLSPEC_HIDDEN; diff --git a/media/doc/README.WINE b/media/doc/README.WINE index 6905a44db6..5f30683e42 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -200,7 +200,7 @@ reactos/dll/win32/windowscodecs # Synced to Wine-3.0 reactos/dll/win32/windowscodecsext # Synced to WineStaging-2.9 reactos/dll/win32/winemp3.acm # Synced to Wine-3.0 reactos/dll/win32/wing32 # Synced to WineStaging-2.9 -reactos/dll/win32/winhttp # Synced to WineStaging-2.16 +reactos/dll/win32/winhttp # Synced to Wine-3.0 reactos/dll/win32/wininet # Synced to WineStaging-2.16 reactos/dll/win32/winmm # Forked at Wine-20050628 reactos/dll/win32/winmm/midimap # Forked at Wine-20050628
6 years, 11 months
1
0
0
0
01/01: [PSDK] Update winhttp.h. CORE-14225
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=4f825146c250485a02161…
commit 4f825146c250485a0216189a5657cf15eadf22ed Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Jan 20 13:54:50 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Jan 20 13:54:50 2018 +0100 [PSDK] Update winhttp.h. CORE-14225 --- sdk/include/psdk/winhttp.h | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/sdk/include/psdk/winhttp.h b/sdk/include/psdk/winhttp.h index 45be58a18e..3ef05ea0bd 100644 --- a/sdk/include/psdk/winhttp.h +++ b/sdk/include/psdk/winhttp.h @@ -440,10 +440,14 @@ typedef int INTERNET_SCHEME, *LPINTERNET_SCHEME; #define WINHTTP_CALLBACK_STATUS_FLAG_CERT_WRONG_USAGE 0x00000040 #define WINHTTP_CALLBACK_STATUS_FLAG_SECURITY_CHANNEL_ERROR 0x80000000 -#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 0x00000008 -#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 0x00000020 -#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 0x00000080 -#define WINHTTP_FLAG_SECURE_PROTOCOL_ALL (WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 | WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 | WINHTTP_FLAG_SECURE_PROTOCOL_TLS1) +#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 0x00000008 +#define WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 0x00000020 +#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1 0x00000080 +#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_1 0x00000200 +#define WINHTTP_FLAG_SECURE_PROTOCOL_TLS1_2 0x00000800 +#define WINHTTP_FLAG_SECURE_PROTOCOL_ALL (WINHTTP_FLAG_SECURE_PROTOCOL_SSL2 |\ + WINHTTP_FLAG_SECURE_PROTOCOL_SSL3 |\ + WINHTTP_FLAG_SECURE_PROTOCOL_TLS1) #define WINHTTP_AUTH_SCHEME_BASIC 0x00000001 #define WINHTTP_AUTH_SCHEME_NTLM 0x00000002
6 years, 11 months
1
0
0
0
01/01: [WINEMP3.ACM] Sync with Wine 3.0. CORE-14225
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c8f158b700fb67cc12262…
commit c8f158b700fb67cc12262ecbf8a1a79f0765cb48 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Jan 20 13:52:52 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Jan 20 13:52:52 2018 +0100 [WINEMP3.ACM] Sync with Wine 3.0. CORE-14225 --- dll/win32/winemp3.acm/mpegl3.c | 95 ++++++++---------------------------------- media/doc/README.WINE | 2 +- 2 files changed, 19 insertions(+), 78 deletions(-) diff --git a/dll/win32/winemp3.acm/mpegl3.c b/dll/win32/winemp3.acm/mpegl3.c index 9c875dca25..15acdeaad5 100644 --- a/dll/win32/winemp3.acm/mpegl3.c +++ b/dll/win32/winemp3.acm/mpegl3.c @@ -215,7 +215,6 @@ static void MPEG3_Reset(PACMDRVSTREAMINSTANCE adsi, AcmMpeg3Data* aad) */ static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi) { - LRESULT error = MMSYSERR_NOTSUPPORTED; AcmMpeg3Data* aad; int err; @@ -239,18 +238,6 @@ static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi) adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEG) && adsi->pwfxDst->wFormatTag == WAVE_FORMAT_PCM) { - if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_MPEGLAYER3) - { - MPEGLAYER3WAVEFORMAT *formatmp3 = (MPEGLAYER3WAVEFORMAT *)adsi->pwfxSrc; - - if (adsi->pwfxSrc->cbSize < MPEGLAYER3_WFX_EXTRA_BYTES || - formatmp3->wID != MPEGLAYER3_ID_MPEG) - { - error = ACMERR_NOTPOSSIBLE; - goto theEnd; - } - } - /* resampling or mono <=> stereo not available * MPEG3 algo only define 16 bit per sample output */ @@ -271,10 +258,13 @@ static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi) mpg123_param(aad->mh, MPG123_ADD_FLAGS, MPG123_IGNORE_INFOFRAME, 0); #endif } - /* no encoding yet else if (adsi->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM && - adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3) - */ + (adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEGLAYER3 || + adsi->pwfxDst->wFormatTag == WAVE_FORMAT_MPEG)) + { + WARN("Encoding to MPEG is not supported\n"); + goto theEnd; + } else goto theEnd; MPEG3_Reset(adsi, aad); @@ -283,7 +273,7 @@ static LRESULT MPEG3_StreamOpen(PACMDRVSTREAMINSTANCE adsi) theEnd: HeapFree(GetProcessHeap(), 0, aad); adsi->dwDriver = 0L; - return error; + return MMSYSERR_NOTSUPPORTED; } /*********************************************************************** @@ -749,54 +739,19 @@ static LRESULT MPEG3_FormatTagDetails(PACMFORMATTAGDETAILSW aftd, DWORD dwQuery) case 1: aftd->dwFormatTag = WAVE_FORMAT_MPEGLAYER3; aftd->cbFormatSize = sizeof(MPEGLAYER3WAVEFORMAT); - aftd->cStandardFormats = NUM_MPEG3_FORMATS; + aftd->cStandardFormats = 0; lstrcpyW(aftd->szFormatTag, szMpeg3); break; case 2: aftd->dwFormatTag = WAVE_FORMAT_MPEG; aftd->cbFormatSize = sizeof(MPEG1WAVEFORMAT); - aftd->cStandardFormats = NUM_MPEG3_FORMATS; + aftd->cStandardFormats = 0; lstrcpyW(aftd->szFormatTag, szMpeg); break; } return MMSYSERR_NOERROR; } -static void fill_in_mp3(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate) -{ - MPEGLAYER3WAVEFORMAT* mp3wfx = (MPEGLAYER3WAVEFORMAT*)wfx; - - wfx->nAvgBytesPerSec = bit_rate / 8; - if (cbwfx >= sizeof(WAVEFORMATEX)) - wfx->cbSize = sizeof(MPEGLAYER3WAVEFORMAT) - sizeof(WAVEFORMATEX); - if (cbwfx >= sizeof(MPEGLAYER3WAVEFORMAT)) - { - mp3wfx->wID = MPEGLAYER3_ID_MPEG; - mp3wfx->fdwFlags = MPEGLAYER3_FLAG_PADDING_OFF; - mp3wfx->nBlockSize = (bit_rate * 144) / wfx->nSamplesPerSec; - mp3wfx->nFramesPerBlock = 1; - mp3wfx->nCodecDelay = 0x0571; - } -} - -static void fill_in_mpeg(unsigned cbwfx, WAVEFORMATEX* wfx, unsigned bit_rate) -{ - MPEG1WAVEFORMAT* mp3wfx = (MPEG1WAVEFORMAT*)wfx; - - wfx->nAvgBytesPerSec = bit_rate / 8; - if (cbwfx >= sizeof(WAVEFORMATEX)) - wfx->cbSize = sizeof(MPEG1WAVEFORMAT) - sizeof(WAVEFORMATEX); - if (cbwfx >= sizeof(MPEG1WAVEFORMAT)) - { - mp3wfx->fwHeadLayer = ACM_MPEG_LAYER3; - mp3wfx->dwHeadBitrate = wfx->nAvgBytesPerSec * 8; - mp3wfx->fwHeadMode = ACM_MPEG_JOINTSTEREO; - mp3wfx->fwHeadModeExt = 0xf; - mp3wfx->wHeadEmphasis = 1; - mp3wfx->fwHeadFlags = ACM_MPEG_ID_MPEG1; - } -} - /*********************************************************************** * MPEG3_FormatDetails * @@ -827,16 +782,8 @@ static LRESULT MPEG3_FormatDetails(PACMFORMATDETAILSW afd, DWORD dwQuery) break; case WAVE_FORMAT_MPEGLAYER3: case WAVE_FORMAT_MPEG: - if (afd->dwFormatIndex >= NUM_MPEG3_FORMATS) return ACMERR_NOTPOSSIBLE; - afd->pwfx->nChannels = MPEG3_Formats[afd->dwFormatIndex].nChannels; - afd->pwfx->nSamplesPerSec = MPEG3_Formats[afd->dwFormatIndex].rate; - afd->pwfx->wBitsPerSample = MPEG3_Formats[afd->dwFormatIndex].nBits; - afd->pwfx->nBlockAlign = 1; - if (afd->dwFormatTag == WAVE_FORMAT_MPEGLAYER3) - fill_in_mp3(afd->cbwfx, afd->pwfx, 192000); - else - fill_in_mpeg(afd->cbwfx, afd->pwfx, 192000); - break; + WARN("Encoding to MPEG is not supported\n"); + return ACMERR_NOTPOSSIBLE; default: WARN("Unsupported tag %08x\n", afd->dwFormatTag); return MMSYSERR_INVALPARAM; @@ -869,18 +816,15 @@ static LRESULT MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs) adfs->pwfxDst->nChannels = adfs->pwfxSrc->nChannels; if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_NSAMPLESPERSEC)) adfs->pwfxDst->nSamplesPerSec = adfs->pwfxSrc->nSamplesPerSec; - if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WBITSPERSAMPLE)) - { - if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) - adfs->pwfxDst->wBitsPerSample = 4; - else - adfs->pwfxDst->wBitsPerSample = 16; - } + adfs->pwfxDst->wBitsPerSample = 16; if (!(adfs->fdwSuggest & ACM_FORMATSUGGESTF_WFORMATTAG)) { if (adfs->pwfxSrc->wFormatTag == WAVE_FORMAT_PCM) - adfs->pwfxDst->wFormatTag = WAVE_FORMAT_MPEGLAYER3; + { + WARN("Encoding to MPEG is not supported\n"); + return ACMERR_NOTPOSSIBLE; + } else adfs->pwfxDst->wFormatTag = WAVE_FORMAT_PCM; } @@ -896,12 +840,9 @@ static LRESULT MPEG3_FormatSuggest(PACMDRVFORMATSUGGEST adfs) adfs->pwfxDst->nAvgBytesPerSec = adfs->pwfxDst->nSamplesPerSec * adfs->pwfxDst->nBlockAlign; break; case WAVE_FORMAT_MPEG: - adfs->pwfxDst->nBlockAlign = 1; - fill_in_mpeg(adfs->cbwfxDst, adfs->pwfxDst, 192000); - break; case WAVE_FORMAT_MPEGLAYER3: - adfs->pwfxDst->nBlockAlign = 1; - fill_in_mp3(adfs->cbwfxDst, adfs->pwfxDst, 192000); + WARN("Encoding to MPEG is not supported\n"); + return ACMERR_NOTPOSSIBLE; break; default: FIXME("\n"); diff --git a/media/doc/README.WINE b/media/doc/README.WINE index d1c733260d..6905a44db6 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -198,7 +198,7 @@ reactos/dll/win32/wbemdisp # Synced to Wine-3.0 reactos/dll/win32/wbemprox # Synced to Wine-3.0 reactos/dll/win32/windowscodecs # Synced to Wine-3.0 reactos/dll/win32/windowscodecsext # Synced to WineStaging-2.9 -reactos/dll/win32/winemp3.acm # Synced to WineStaging-2.16 +reactos/dll/win32/winemp3.acm # Synced to Wine-3.0 reactos/dll/win32/wing32 # Synced to WineStaging-2.9 reactos/dll/win32/winhttp # Synced to WineStaging-2.16 reactos/dll/win32/wininet # Synced to WineStaging-2.16
6 years, 11 months
1
0
0
0
01/01: [WINDOWSCODECS_WINETEST] Sync with Wine 3.0. CORE-14225
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=a5cb9a0a8df9630613474…
commit a5cb9a0a8df9630613474b539dfe163945d71843 Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Jan 20 13:51:37 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Jan 20 13:51:37 2018 +0100 [WINDOWSCODECS_WINETEST] Sync with Wine 3.0. CORE-14225 --- .../rostests/winetests/windowscodecs/converter.c | 809 ++------------------- modules/rostests/winetests/windowscodecs/palette.c | 139 +--- .../rostests/winetests/windowscodecs/pngformat.c | 14 +- .../rostests/winetests/windowscodecs/tiffformat.c | 614 +--------------- 4 files changed, 111 insertions(+), 1465 deletions(-) diff --git a/modules/rostests/winetests/windowscodecs/converter.c b/modules/rostests/winetests/windowscodecs/converter.c index baa7a9d3c4..2a44ef50b0 100644 --- a/modules/rostests/winetests/windowscodecs/converter.c +++ b/modules/rostests/winetests/windowscodecs/converter.c @@ -107,30 +107,9 @@ static HRESULT WINAPI BitmapTestSrc_GetResolution(IWICBitmapSource *iface, } static HRESULT WINAPI BitmapTestSrc_CopyPalette(IWICBitmapSource *iface, - IWICPalette *palette) + IWICPalette *pIPalette) { - BitmapTestSrc *This = impl_from_IWICBitmapSource(iface); - - if (IsEqualGUID(This->data->format, &GUID_WICPixelFormat1bppIndexed) || - IsEqualGUID(This->data->format, &GUID_WICPixelFormat2bppIndexed) || - IsEqualGUID(This->data->format, &GUID_WICPixelFormat4bppIndexed) || - IsEqualGUID(This->data->format, &GUID_WICPixelFormat8bppIndexed)) - { - WICColor colors[8]; - - colors[0] = 0xff0000ff; - colors[1] = 0xff00ff00; - colors[2] = 0xffff0000; - colors[3] = 0xff000000; - colors[4] = 0xffffff00; - colors[5] = 0xffff00ff; - colors[6] = 0xff00ffff; - colors[7] = 0xffffffff; - return IWICPalette_InitializeCustom(palette, colors, 8); - } - - /* unique error marker */ - return 0xdeadbeef; + return E_NOTIMPL; } static HRESULT WINAPI BitmapTestSrc_CopyPixels(IWICBitmapSource *iface, @@ -262,58 +241,16 @@ static BOOL compare_bits(const struct bitmap_data *expect, UINT buffersize, cons break; } } - else if (IsEqualGUID(expect->format, &GUID_WICPixelFormat2bppIndexed) || - IsEqualGUID(expect->format, &GUID_WICPixelFormat4bppIndexed) || - IsEqualGUID(expect->format, &GUID_WICPixelFormat8bppIndexed)) - { - UINT i; - const BYTE *a=(const BYTE*)expect->bits, *b=(const BYTE*)converted_bits; - equal=TRUE; - - for (i=0; i<buffersize; i++) - if (a[i] != b[i]) - { - equal = FALSE; - break; - } - } else equal = (memcmp(expect->bits, converted_bits, buffersize) == 0); if (!equal && expect->alt_data) equal = compare_bits(expect->alt_data, buffersize, converted_bits); - if (!equal && winetest_debug > 1) - { - UINT i, bps; - bps = expect->bpp / 8; - if (!bps) bps = buffersize; - printf("converted_bits (%u bytes):\n ", buffersize); - for (i = 0; i < buffersize; i++) - { - printf("%u,", converted_bits[i]); - if (!((i + 1) % 32)) printf("\n "); - else if (!((i+1) % bps)) printf(" "); - } - printf("\n"); - } - return equal; } -static BOOL is_indexed_format(const GUID *format) -{ - if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed) || - IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed) || - IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed) || - IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed)) - return TRUE; - - return FALSE; -} - -static void compare_bitmap_data(const struct bitmap_data *src, const struct bitmap_data *expect, - IWICBitmapSource *source, const char *name) +static void compare_bitmap_data(const struct bitmap_data *expect, IWICBitmapSource *source, const char *name) { BYTE *converted_bits; UINT width, height; @@ -346,24 +283,15 @@ static void compare_bitmap_data(const struct bitmap_data *src, const struct bitm buffersize = stride * expect->height; converted_bits = HeapAlloc(GetProcessHeap(), 0, buffersize); - memset(converted_bits, 0xaa, buffersize); hr = IWICBitmapSource_CopyPixels(source, &prc, stride, buffersize, converted_bits); ok(SUCCEEDED(hr), "CopyPixels(%s) failed, hr=%x\n", name, hr); - - /* The result of conversion of color to indexed formats depends on - * optimized palette generation implementation. We either need to - * assign our own palette, or just skip the comparison. - */ - if (!(!is_indexed_format(src->format) && is_indexed_format(expect->format))) - ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name); + ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name); /* Test with NULL rectangle - should copy the whole bitmap */ memset(converted_bits, 0xaa, buffersize); hr = IWICBitmapSource_CopyPixels(source, NULL, stride, buffersize, converted_bits); ok(SUCCEEDED(hr), "CopyPixels(%s,rc=NULL) failed, hr=%x\n", name, hr); - /* see comment above */ - if (!(!is_indexed_format(src->format) && is_indexed_format(expect->format))) - ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name); + ok(compare_bits(expect, buffersize, converted_bits), "unexpected pixel data (%s)\n", name); HeapFree(GetProcessHeap(), 0, converted_bits); } @@ -377,161 +305,66 @@ static const struct bitmap_data testdata_BlackWhite = { static const struct bitmap_data testdata_1bppIndexed = { &GUID_WICPixelFormat1bppIndexed, 1, bits_1bpp, 32, 2, 96.0, 96.0}; -/* some encoders (like BMP) require data to be 4-bytes aligned */ -static const BYTE bits_2bpp[] = { - 0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb,0xdb, - 0x24,0x24,0x24,0x24,0x24,0x24,0x24,0x24}; -static const struct bitmap_data testdata_2bppIndexed = { - &GUID_WICPixelFormat2bppIndexed, 2, bits_2bpp, 32, 2, 96.0, 96.0}; - -/* some encoders (like BMP) require data to be 4-bytes aligned */ -static const BYTE bits_4bpp[] = { - 0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23,0x01,0x23, - 0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67,0x45,0x67}; - -static const struct bitmap_data testdata_4bppIndexed = { - &GUID_WICPixelFormat4bppIndexed, 4, bits_4bpp, 32, 2, 96.0, 96.0}; - -static const BYTE bits_8bpp_BW[] = { - 0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1, - 1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0,1,0}; -static const struct bitmap_data testdata_8bppIndexed_BW = { - &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp_BW, 32, 2, 96.0, 96.0}; - -static const BYTE bits_8bpp_4colors[] = { - 0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0,0,1,2,0, - 3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3,3,2,1,3}; -static const struct bitmap_data testdata_8bppIndexed_4colors = { - &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp_4colors, 32, 2, 96.0, 96.0}; - static const BYTE bits_8bpp[] = { - 0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3,0,1,2,3, - 4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7,4,5,6,7}; + 0,1,2,3, + 4,5,6,7}; static const struct bitmap_data testdata_8bppIndexed = { - &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp, 32, 2, 96.0, 96.0}; + &GUID_WICPixelFormat8bppIndexed, 8, bits_8bpp, 4, 2, 96.0, 96.0}; static const BYTE bits_24bppBGR[] = { - 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0, - 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0, - 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0, - 255,0,0, 0,255,0, 0,0,255, 0,0,0, 255,0,0, 0,255,0, 0,0,255, 0,0,0, - 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255, - 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255, - 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255, - 0,255,255, 255,0,255, 255,255,0, 255,255,255, 0,255,255, 255,0,255, 255,255,0, 255,255,255}; + 255,0,0, 0,255,0, 0,0,255, 0,0,0, + 0,255,255, 255,0,255, 255,255,0, 255,255,255}; static const struct bitmap_data testdata_24bppBGR = { - &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 32, 2, 96.0, 96.0}; + &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR, 4, 2, 96.0, 96.0}; static const BYTE bits_24bppRGB[] = { - 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0, - 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0, - 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0, - 0,0,255, 0,255,0, 255,0,0, 0,0,0, 0,0,255, 0,255,0, 255,0,0, 0,0,0, - 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255, - 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255, - 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255, - 255,255,0, 255,0,255, 0,255,255, 255,255,255, 255,255,0, 255,0,255, 0,255,255, 255,255,255 }; + 0,0,255, 0,255,0, 255,0,0, 0,0,0, + 255,255,0, 255,0,255, 0,255,255, 255,255,255}; static const struct bitmap_data testdata_24bppRGB = { - &GUID_WICPixelFormat24bppRGB, 24, bits_24bppRGB, 32, 2, 96.0, 96.0}; + &GUID_WICPixelFormat24bppRGB, 24, bits_24bppRGB, 4, 2, 96.0, 96.0}; static const BYTE bits_32bppBGR[] = { - 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, - 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, - 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, - 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, - 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, - 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, - 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, - 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80, 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80}; + 255,0,0,80, 0,255,0,80, 0,0,255,80, 0,0,0,80, + 0,255,255,80, 255,0,255,80, 255,255,0,80, 255,255,255,80}; static const struct bitmap_data testdata_32bppBGR = { - &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 32, 2, 96.0, 96.0}; -static const struct bitmap_data testdata_32bppBGRA80 = { - &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGR, 32, 2, 96.0, 96.0}; -static const struct bitmap_data testdata_32bppRGBA80 = { - &GUID_WICPixelFormat32bppRGBA, 32, bits_32bppBGR, 32, 2, 96.0, 96.0}; + &GUID_WICPixelFormat32bppBGR, 32, bits_32bppBGR, 4, 2, 96.0, 96.0}; static const BYTE bits_32bppBGRA[] = { - 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, - 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, - 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, - 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, - 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, - 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, - 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, - 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255, 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255}; + 255,0,0,255, 0,255,0,255, 0,0,255,255, 0,0,0,255, + 0,255,255,255, 255,0,255,255, 255,255,0,255, 255,255,255,255}; static const struct bitmap_data testdata_32bppBGRA = { - &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0}; -static const struct bitmap_data testdata_32bppRGBA = { - &GUID_WICPixelFormat32bppRGBA, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0}; -static const struct bitmap_data testdata_32bppRGB = { - &GUID_WICPixelFormat32bppRGB, 32, bits_32bppBGRA, 32, 2, 96.0, 96.0}; - -static const BYTE bits_32bppPBGRA[] = { - 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, - 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, - 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, - 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, 80,0,0,80, 0,80,0,80, 0,0,80,80, 0,0,0,80, - 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, - 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, - 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, - 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80, 0,80,80,80, 80,0,80,80, 80,80,0,80, 80,80,80,80}; -static const struct bitmap_data testdata_32bppPBGRA = { - &GUID_WICPixelFormat32bppPBGRA, 32, bits_32bppPBGRA, 32, 2, 96.0, 96.0}; -static const struct bitmap_data testdata_32bppPRGBA = { - &GUID_WICPixelFormat32bppPRGBA, 32, bits_32bppPBGRA, 32, 2, 96.0, 96.0}; + &GUID_WICPixelFormat32bppBGRA, 32, bits_32bppBGRA, 4, 2, 96.0, 96.0}; /* XP and 2003 use linear color conversion, later versions use sRGB gamma */ static const float bits_32bppGrayFloat_xp[] = { - 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f, - 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f, - 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f, - 0.114000f,0.587000f,0.299000f,0.000000f,0.114000f,0.587000f,0.299000f,0.000000f, - 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f, - 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f, - 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f, - 0.886000f,0.413000f,0.701000f,1.000000f,0.886000f,0.413000f,0.701000f,1.000000f}; + 0.114000f,0.587000f,0.299000f,0.000000f, + 0.886000f,0.413000f,0.701000f,1.000000f}; static const struct bitmap_data testdata_32bppGrayFloat_xp = { - &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat_xp, 32, 2, 96.0, 96.0}; + &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat_xp, 4, 2, 96.0, 96.0}; static const float bits_32bppGrayFloat[] = { - 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f, - 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f, - 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f, - 0.072200f,0.715200f,0.212600f,0.000000f,0.072200f,0.715200f,0.212600f,0.000000f, - 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f, - 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f, - 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f, - 0.927800f,0.284800f,0.787400f,1.000000f,0.927800f,0.284800f,0.787400f,1.000000f}; + 0.072200f,0.715200f,0.212600f,0.000000f, + 0.927800f,0.284800f,0.787400f,1.000000f}; static const struct bitmap_data testdata_32bppGrayFloat = { - &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat, 32, 2, 96.0, 96.0, &testdata_32bppGrayFloat_xp}; + &GUID_WICPixelFormat32bppGrayFloat, 32, (const BYTE *)bits_32bppGrayFloat, 4, 2, 96.0, 96.0, &testdata_32bppGrayFloat_xp}; static const BYTE bits_8bppGray_xp[] = { - 29,150,76,0,29,150,76,0,29,150,76,0,29,150,76,0, - 29,150,76,0,29,150,76,0,29,150,76,0,29,150,76,0, - 226,105,179,255,226,105,179,255,226,105,179,255,226,105,179,255, - 226,105,179,255,226,105,179,255,226,105,179,255,226,105,179,255}; + 29,150,76,0, + 226,105,179,255}; static const struct bitmap_data testdata_8bppGray_xp = { - &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray_xp, 32, 2, 96.0, 96.0}; + &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray_xp, 4, 2, 96.0, 96.0}; static const BYTE bits_8bppGray[] = { - 76,220,127,0,76,220,127,0,76,220,127,0,76,220,127,0, - 76,220,127,0,76,220,127,0,76,220,127,0,76,220,127,0, - 247,145,230,255,247,145,230,255,247,145,230,255,247,145,230,255, - 247,145,230,255,247,145,230,255,247,145,230,255,247,145,230,255}; + 76,220,127,0, + 247,145,230,255}; static const struct bitmap_data testdata_8bppGray = { - &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray, 32, 2, 96.0, 96.0, &testdata_8bppGray_xp}; + &GUID_WICPixelFormat8bppGray, 8, bits_8bppGray, 4, 2, 96.0, 96.0, &testdata_8bppGray_xp}; static const BYTE bits_24bppBGR_gray[] = { - 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0, - 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0, - 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0, - 76,76,76, 220,220,220, 127,127,127, 0,0,0, 76,76,76, 220,220,220, 127,127,127, 0,0,0, - 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255, - 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255, - 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255, - 247,247,247, 145,145,145, 230,230,230, 255,255,255, 247,247,247, 145,145,145, 230,230,230, 255,255,255}; + 76,76,76, 220,220,220, 127,127,127, 0,0,0, + 247,247,247, 145,145,145, 230,230,230, 255,255,255}; static const struct bitmap_data testdata_24bppBGR_gray = { - &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR_gray, 32, 2, 96.0, 96.0}; + &GUID_WICPixelFormat24bppBGR, 24, bits_24bppBGR_gray, 4, 2, 96.0, 96.0}; static void test_conversion(const struct bitmap_data *src, const struct bitmap_data *dst, const char *name, BOOL todo) { @@ -543,12 +376,11 @@ static void test_conversion(const struct bitmap_data *src, const struct bitmap_d hr = WICConvertBitmapSource(dst->format, &src_obj->IWICBitmapSource_iface, &dst_bitmap); todo_wine_if (todo) - ok(hr == S_OK || - broken(hr == E_INVALIDARG || hr == WINCODEC_ERR_COMPONENTNOTFOUND) /* XP */, "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr); + ok(SUCCEEDED(hr), "WICConvertBitmapSource(%s) failed, hr=%x\n", name, hr); - if (hr == S_OK) + if (SUCCEEDED(hr)) { - compare_bitmap_data(src, dst, dst_bitmap, name); + compare_bitmap_data(dst, dst_bitmap, name); IWICBitmapSource_Release(dst_bitmap); } @@ -596,7 +428,7 @@ static void test_default_converter(void) ok(SUCCEEDED(hr), "Initialize returned %x\n", hr); if (SUCCEEDED(hr)) - compare_bitmap_data(&testdata_32bppBGRA, &testdata_32bppBGR, (IWICBitmapSource*)converter, "default converter"); + compare_bitmap_data(&testdata_32bppBGR, (IWICBitmapSource*)converter, "default converter"); IWICFormatConverter_Release(converter); } @@ -781,232 +613,14 @@ static void test_encoder_properties(const CLSID* clsid_encoder, IPropertyBag2 *o } } -static void load_stream(IUnknown *reader, IStream *stream) +static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format) { - HRESULT hr; - IWICPersistStream *persist; -#ifdef WORDS_BIGENDIAN - DWORD persist_options = WICPersistOptionBigEndian; -#else - DWORD persist_options = WICPersistOptionLittleEndian; -#endif - - hr = IUnknown_QueryInterface(reader, &IID_IWICPersistStream, (void **)&persist); - ok(hr == S_OK, "QueryInterface failed, hr=%x\n", hr); - - hr = IWICPersistStream_LoadEx(persist, stream, NULL, persist_options); - ok(hr == S_OK, "LoadEx failed, hr=%x\n", hr); - - IWICPersistStream_Release(persist); + /* FIXME */ } static void check_tiff_format(IStream *stream, const WICPixelFormatGUID *format) { - HRESULT hr; - IWICMetadataReader *reader; - PROPVARIANT id, value; - struct - { - USHORT byte_order; - USHORT version; - ULONG dir_offset; - } tiff; - LARGE_INTEGER pos; - UINT count, i; - int width, height, bps, photo, samples, colormap; - struct - { - int id, *value; - } tag[] = - { - { 0x100, &width }, { 0x101, &height }, { 0x102, &bps }, - { 0x106, &photo }, { 0x115, &samples }, { 0x140, &colormap } - }; - - memset(&tiff, 0, sizeof(tiff)); - hr = IStream_Read(stream, &tiff, sizeof(tiff), NULL); - ok(hr == S_OK, "IStream_Read error %#x\n", hr); - ok(tiff.byte_order == MAKEWORD('I','I') || tiff.byte_order == MAKEWORD('M','M'), - "wrong TIFF byte order mark %02x\n", tiff.byte_order); - ok(tiff.version == 42, "wrong TIFF version %u\n", tiff.version); - - pos.QuadPart = tiff.dir_offset; - hr = IStream_Seek(stream, pos, SEEK_SET, NULL); - ok(hr == S_OK, "IStream_Seek error %#x\n", hr); - - hr = CoCreateInstance(&CLSID_WICIfdMetadataReader, NULL, CLSCTX_INPROC_SERVER, - &IID_IWICMetadataReader, (void **)&reader); - ok(hr == S_OK, "CoCreateInstance error %#x\n", hr); - - load_stream((IUnknown *)reader, stream); - - hr = IWICMetadataReader_GetCount(reader, &count); - ok(hr == S_OK, "GetCount error %#x\n", hr); - ok(count != 0, "wrong count %u\n", count); - - for (i = 0; i < sizeof(tag)/sizeof(tag[0]); i++) - { - PropVariantInit(&id); - PropVariantInit(&value); - - id.vt = VT_UI2; - U(id).uiVal = tag[i].id; - hr = IWICMetadataReader_GetValue(reader, NULL, &id, &value); - ok(hr == S_OK || (tag[i].id == 0x140 && hr == WINCODEC_ERR_PROPERTYNOTFOUND), - "GetValue(%04x) error %#x\n", tag[i].id, hr); - if (hr == S_OK) - { - ok(value.vt == VT_UI2 || value.vt == VT_UI4 || value.vt == (VT_UI2 | VT_VECTOR), "wrong vt: %d\n", value.vt); - tag[i].value[0] = U(value).uiVal; - } - else - tag[i].value[0] = -1; - } - - IWICMetadataReader_Release(reader); - - if (IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite)) - { - ok(width == 32, "wrong width %u\n", width); - ok(height == 2, "wrong height %u\n", height); - - ok(bps == 1, "wrong bps %d\n", bps); - ok(photo == 1, "wrong photometric %d\n", photo); - ok(samples == 1, "wrong samples %d\n", samples); - ok(colormap == -1, "wrong colormap %d\n", colormap); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed)) - { - ok(width == 32, "wrong width %u\n", width); - ok(height == 2, "wrong height %u\n", height); - - ok(bps == 1, "wrong bps %d\n", bps); - ok(photo == 3, "wrong photometric %d\n", photo); - ok(samples == 1, "wrong samples %d\n", samples); - ok(colormap == 6, "wrong colormap %d\n", colormap); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed)) - { - ok(width == 32, "wrong width %u\n", width); - ok(height == 2, "wrong height %u\n", height); - - ok(bps == 2, "wrong bps %d\n", bps); - ok(photo == 3, "wrong photometric %d\n", photo); - ok(samples == 1, "wrong samples %d\n", samples); - ok(colormap == 12, "wrong colormap %d\n", colormap); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed)) - { - ok(width == 32, "wrong width %u\n", width); - ok(height == 2, "wrong height %u\n", height); - - ok(bps == 4, "wrong bps %d\n", bps); - ok(photo == 3, "wrong photometric %d\n", photo); - ok(samples == 1, "wrong samples %d\n", samples); - ok(colormap == 48, "wrong colormap %d\n", colormap); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed)) - { - ok(width == 32, "wrong width %u\n", width); - ok(height == 2, "wrong height %u\n", height); - - ok(bps == 8, "wrong bps %d\n", bps); - ok(photo == 3, "wrong photometric %d\n", photo); - ok(samples == 1, "wrong samples %d\n", samples); - ok(colormap == 768, "wrong colormap %d\n", colormap); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR)) - { - ok(width == 32, "wrong width %u\n", width); - ok(height == 2, "wrong height %u\n", height); - - ok(bps == 3, "wrong bps %d\n", bps); - ok(photo == 2, "wrong photometric %d\n", photo); - ok(samples == 3, "wrong samples %d\n", samples); - ok(colormap == -1, "wrong colormap %d\n", colormap); - } - else - ok(0, "unknown TIFF pixel format %s\n", wine_dbgstr_guid(format)); -} - -static void check_bmp_format(IStream *stream, const WICPixelFormatGUID *format) -{ - HRESULT hr; - BITMAPFILEHEADER bfh; - BITMAPV5HEADER bih; - - hr = IStream_Read(stream, &bfh, sizeof(bfh), NULL); - ok(hr == S_OK, "IStream_Read error %#x\n", hr); - - ok(bfh.bfType == 0x4d42, "wrong BMP signature %02x\n", bfh.bfType); - ok(bfh.bfReserved1 == 0, "wrong bfReserved1 %02x\n", bfh.bfReserved1); - ok(bfh.bfReserved2 == 0, "wrong bfReserved2 %02x\n", bfh.bfReserved2); - - hr = IStream_Read(stream, &bih, sizeof(bih), NULL); - ok(hr == S_OK, "IStream_Read error %#x\n", hr); - - if (IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed)) - { - ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits); - - ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width); - ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height); - - ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes); - ok(bih.bV5BitCount == 1, "wrong BitCount %d\n", bih.bV5BitCount); - ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed); - ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed)) - { - ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits); - - ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width); - ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height); - - ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes); - ok(bih.bV5BitCount == 2, "wrong BitCount %d\n", bih.bV5BitCount); - ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed); - ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed)) - { - ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits); - - ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width); - ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height); - - ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes); - ok(bih.bV5BitCount == 4, "wrong BitCount %d\n", bih.bV5BitCount); - ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed); - ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed)) - { - ok(bfh.bfOffBits == 0x0436, "wrong bfOffBits %08x\n", bfh.bfOffBits); - - ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width); - ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height); - - ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes); - ok(bih.bV5BitCount == 8, "wrong BitCount %d\n", bih.bV5BitCount); - ok(bih.bV5ClrUsed == 256, "wrong ClrUsed %d\n", bih.bV5ClrUsed); - ok(bih.bV5ClrImportant == 256, "wrong ClrImportant %d\n", bih.bV5ClrImportant); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat32bppBGR)) - { - ok(bfh.bfOffBits == 0x0036, "wrong bfOffBits %08x\n", bfh.bfOffBits); - - ok(bih.bV5Width == 32, "wrong width %u\n", bih.bV5Width); - ok(bih.bV5Height == 2, "wrong height %u\n", bih.bV5Height); - - ok(bih.bV5Planes == 1, "wrong Planes %d\n", bih.bV5Planes); - ok(bih.bV5BitCount == 32, "wrong BitCount %d\n", bih.bV5BitCount); - ok(bih.bV5ClrUsed == 0, "wrong ClrUsed %d\n", bih.bV5ClrUsed); - ok(bih.bV5ClrImportant == 0, "wrong ClrImportant %d\n", bih.bV5ClrImportant); - } - else - ok(0, "unknown BMP pixel format %s\n", wine_dbgstr_guid(format)); + /* FIXME */ } static unsigned be_uint(unsigned val) @@ -1063,31 +677,9 @@ static void check_png_format(IStream *stream, const WICPixelFormatGUID *format) ok(png.filter == 0, "wrong filter %d\n", png.filter); ok(png.interlace == 0, "wrong interlace %d\n", png.interlace); } - else if (IsEqualGUID(format, &GUID_WICPixelFormat2bppIndexed)) - { - ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width)); - ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height)); - - ok(png.bit_depth == 2, "wrong bit_depth %d\n", png.bit_depth); - ok(png.color_type == 3, "wrong color_type %d\n", png.color_type); - ok(png.compression == 0, "wrong compression %d\n", png.compression); - ok(png.filter == 0, "wrong filter %d\n", png.filter); - ok(png.interlace == 0, "wrong interlace %d\n", png.interlace); - } - else if (IsEqualGUID(format, &GUID_WICPixelFormat4bppIndexed)) - { - ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width)); - ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height)); - - ok(png.bit_depth == 4, "wrong bit_depth %d\n", png.bit_depth); - ok(png.color_type == 3, "wrong color_type %d\n", png.color_type); - ok(png.compression == 0, "wrong compression %d\n", png.compression); - ok(png.filter == 0, "wrong filter %d\n", png.filter); - ok(png.interlace == 0, "wrong interlace %d\n", png.interlace); - } else if (IsEqualGUID(format, &GUID_WICPixelFormat8bppIndexed)) { - ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width)); + ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width)); ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height)); ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth); @@ -1098,7 +690,7 @@ static void check_png_format(IStream *stream, const WICPixelFormatGUID *format) } else if (IsEqualGUID(format, &GUID_WICPixelFormat24bppBGR)) { - ok(be_uint(png.width) == 32, "wrong width %u\n", be_uint(png.width)); + ok(be_uint(png.width) == 4, "wrong width %u\n", be_uint(png.width)); ok(be_uint(png.height) == 2, "wrong height %u\n", be_uint(png.height)); ok(png.bit_depth == 8, "wrong bit_depth %d\n", png.bit_depth); @@ -1111,40 +703,6 @@ static void check_png_format(IStream *stream, const WICPixelFormatGUID *format) ok(0, "unknown PNG pixel format %s\n", wine_dbgstr_guid(format)); } -static void check_gif_format(IStream *stream, const WICPixelFormatGUID *format) -{ -#include "pshpack1.h" - struct logical_screen_descriptor - { - char signature[6]; - USHORT width; - USHORT height; - BYTE packed; - /* global_color_table_flag : 1; - * color_resolution : 3; - * sort_flag : 1; - * global_color_table_size : 3; - */ - BYTE background_color_index; - BYTE pixel_aspect_ratio; - } lsd; -#include "poppack.h" - UINT color_resolution; - HRESULT hr; - - memset(&lsd, 0, sizeof(lsd)); - hr = IStream_Read(stream, &lsd, sizeof(lsd), NULL); - ok(hr == S_OK, "IStream_Read error %#x\n", hr); - - ok(!memcmp(lsd.signature, "GIF89a", 6), "wrong GIF signature %.6s\n", lsd.signature); - - ok(lsd.width == 32, "wrong width %u\n", lsd.width); - ok(lsd.height == 2, "wrong height %u\n", lsd.height); - color_resolution = 1 << (((lsd.packed >> 4) & 0x07) + 1); - ok(color_resolution == 256, "wrong color resolution %u\n", color_resolution); - ok(lsd.pixel_aspect_ratio == 0, "wrong pixel_aspect_ratio %u\n", lsd.pixel_aspect_ratio); -} - static void check_bitmap_format(IStream *stream, const CLSID *encoder, const WICPixelFormatGUID *format) { HRESULT hr; @@ -1160,8 +718,6 @@ static void check_bitmap_format(IStream *stream, const CLSID *encoder, const WIC check_bmp_format(stream, format); else if (IsEqualGUID(encoder, &CLSID_WICTiffEncoder)) check_tiff_format(stream, format); - else if (IsEqualGUID(encoder, &CLSID_WICGifEncoder)) - check_gif_format(stream, format); else ok(0, "unknown encoder %s\n", wine_dbgstr_guid(encoder)); @@ -1238,7 +794,7 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls hr = CoCreateInstance(clsid_encoder, NULL, CLSCTX_INPROC_SERVER, &IID_IWICBitmapEncoder, (void**)&encoder); - ok(SUCCEEDED(hr), "CoCreateInstance(%s) failed, hr=%x\n", wine_dbgstr_guid(clsid_encoder), hr); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); if (SUCCEEDED(hr)) { hglobal = GlobalAlloc(GMEM_MOVEABLE, 0); @@ -1263,10 +819,7 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls if (palette) { hr = IWICBitmapEncoder_SetPalette(encoder, palette); - if (IsEqualGUID(clsid_encoder, &CLSID_WICGifEncoder)) - ok(hr == S_OK, "SetPalette failed, hr=%#x\n", hr); - else - ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "wrong error %#x\n", hr); + ok(hr == WINCODEC_ERR_UNSUPPORTEDOPERATION, "wrong error %#x\n", hr); hr = S_OK; } @@ -1315,10 +868,8 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls memcpy(&pixelformat, srcs[i]->format, sizeof(GUID)); hr = IWICBitmapFrameEncode_SetPixelFormat(frameencode, &pixelformat); ok(SUCCEEDED(hr), "SetPixelFormat failed, hr=%x\n", hr); - ok(IsEqualGUID(&pixelformat, dsts[i]->format) || - broken(IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)) || - broken(IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2 && IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)), - "SetPixelFormat changed the format to %s (%s)\n", wine_dbgstr_guid(&pixelformat), name); + ok(IsEqualGUID(&pixelformat, dsts[i]->format), "SetPixelFormat changed the format to %s (%s)\n", + wine_dbgstr_guid(&pixelformat), name); hr = IWICBitmapFrameEncode_SetSize(frameencode, srcs[i]->width, srcs[i]->height); ok(SUCCEEDED(hr), "SetSize failed, hr=%x\n", hr); @@ -1353,8 +904,6 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls ok(SUCCEEDED(hr), "WriteSource(%dx%d) failed, hr=%x (%s)\n", rc->Width, rc->Height, hr, name); else ok(hr == S_OK || - broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && srcs[i]->bpp == 2) /* XP */ || - broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICTiffEncoder) && srcs[i]->bpp == 2) /* XP */ || broken(hr == E_INVALIDARG && IsEqualGUID(clsid_encoder, &CLSID_WICBmpEncoder) && IsEqualGUID(srcs[i]->format, &GUID_WICPixelFormatBlackWhite)) /* XP */, "WriteSource(NULL) failed, hr=%x (%s)\n", hr, name); } @@ -1386,8 +935,7 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls hr = IWICBitmapEncoder_Commit(encoder); ok(SUCCEEDED(hr), "Commit failed, hr=%x\n", hr); - if (IsEqualGUID(&pixelformat, dsts[0]->format)) - check_bitmap_format(stream, clsid_encoder, dsts[0]->format); + check_bitmap_format(stream, clsid_encoder, dsts[0]->format); } if (SUCCEEDED(hr)) @@ -1405,19 +953,13 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls ok(hr == S_OK, "CreatePalette error %#x\n", hr); hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette); - if (IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder)) - ok(hr == WINCODEC_ERR_WRONGSTATE, "wrong error %#x\n", hr); - else - ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr); + ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr); hr = IWICBitmapDecoder_Initialize(decoder, stream, WICDecodeMetadataCacheOnDemand); ok(SUCCEEDED(hr), "Initialize failed, hr=%x\n", hr); hr = IWICBitmapDecoder_CopyPalette(decoder, frame_palette); - if (IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder)) - ok(hr == S_OK || broken(hr == WINCODEC_ERR_FRAMEMISSING) /* XP */, "CopyPalette failed, hr=%#x\n", hr); - else - ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr); + ok(hr == WINCODEC_ERR_PALETTEUNAVAILABLE, "wrong error %#x\n", hr); hr = S_OK; i=0; @@ -1428,10 +970,7 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls if (SUCCEEDED(hr)) { - hr = IWICBitmapFrameDecode_GetPixelFormat(framedecode, &pixelformat); - ok(hr == S_OK, "GetPixelFormat) failed, hr=%x (%s)\n", hr, name); - if (IsEqualGUID(&pixelformat, dsts[i]->format)) - compare_bitmap_data(srcs[i], dsts[i], (IWICBitmapSource*)framedecode, name); + compare_bitmap_data(dsts[i], (IWICBitmapSource*)framedecode, name); hr = IWICBitmapFrameDecode_CopyPalette(framedecode, frame_palette); if (winetest_debug > 1) @@ -1456,12 +995,7 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls ok(ret == count, "expected %u, got %u\n", count, ret); if (IsEqualGUID(clsid_decoder, &CLSID_WICPngDecoder)) { - /* Newer libpng versions don't accept larger palettes than the declared - * bit depth, so we need to generate the palette of the correct length. - */ - ok(count == 256 || (dsts[i]->bpp == 1 && count == 2) || - (dsts[i]->bpp == 2 && count == 4) || (dsts[i]->bpp == 4 && count == 16), - "expected 256, got %u (%s)\n", count, name); + ok(count == 256 || count == 2 /* newer libpng versions */, "expected 256, got %u (%s)\n", count, name); ok(colors[0] == 0x11111111, "got %08x (%s)\n", colors[0], name); ok(colors[1] == 0x22222222, "got %08x (%s)\n", colors[1], name); @@ -1469,19 +1003,15 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls { ok(colors[2] == 0x33333333, "got %08x (%s)\n", colors[2], name); ok(colors[3] == 0x44444444, "got %08x (%s)\n", colors[3], name); - if (count > 4) - { - ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name); - ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name); - } + ok(colors[4] == 0x55555555, "got %08x (%s)\n", colors[4], name); + ok(colors[5] == 0, "got %08x (%s)\n", colors[5], name); } } else if (IsEqualGUID(clsid_decoder, &CLSID_WICBmpDecoder) || - IsEqualGUID(clsid_decoder, &CLSID_WICTiffDecoder) || - IsEqualGUID(clsid_decoder, &CLSID_WICGifDecoder)) + IsEqualGUID(clsid_decoder, &CLSID_WICTiffDecoder)) { - if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormatBlackWhite) || - IsEqualGUID(&pixelformat, &GUID_WICPixelFormat8bppIndexed)) + if (IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormatBlackWhite) || + IsEqualGUID(dsts[i]->format, &GUID_WICPixelFormat8bppIndexed)) { ok(count == 256, "expected 256, got %u (%s)\n", count, name); @@ -1492,26 +1022,6 @@ static void test_multi_encoder(const struct bitmap_data **srcs, const CLSID* cls ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name); ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name); } - else if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormat2bppIndexed)) - { - ok(count == 4, "expected 4, got %u (%s)\n", count, name); - - ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name); - ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name); - ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name); - ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name); - } - else if (IsEqualGUID(&pixelformat, &GUID_WICPixelFormat4bppIndexed)) - { - ok(count == 16, "expected 16, got %u (%s)\n", count, name); - - ok(colors[0] == 0xff111111, "got %08x (%s)\n", colors[0], name); - ok(colors[1] == 0xff222222, "got %08x (%s)\n", colors[1], name); - ok(colors[2] == 0xff333333, "got %08x (%s)\n", colors[2], name); - ok(colors[3] == 0xff444444, "got %08x (%s)\n", colors[3], name); - ok(colors[4] == 0xff555555, "got %08x (%s)\n", colors[4], name); - ok(colors[5] == 0xff000000, "got %08x (%s)\n", colors[5], name); - } else { ok(count == 2, "expected 2, got %u (%s)\n", count, name); @@ -1591,7 +1101,7 @@ static void test_encoder_rects(void) rc.X = 0; rc.Y = 0; - rc.Width = 32; + rc.Width = 4; rc.Height = 2; test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects full", NULL); @@ -1602,7 +1112,7 @@ static void test_encoder_rects(void) rc.Width = -1; test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects width=-1", NULL); - rc.Width = 32; + rc.Width = 4; rc.Height = 0; test_multi_encoder(srcs, &CLSID_WICTiffEncoder, dsts, &CLSID_WICTiffDecoder, &rc, NULL, "test_encoder_rects height=0", NULL); @@ -1624,163 +1134,6 @@ static const struct setting png_interlace_settings[] = { {NULL} }; -static void test_converter_8bppIndexed(void) -{ - HRESULT hr; - BitmapTestSrc *src_obj; - IWICFormatConverter *converter; - IWICPalette *palette; - UINT count, i; - BYTE buf[32 * 2 * 3]; /* enough to hold 32x2 24bppBGR data */ - - CreateTestBitmap(&testdata_24bppBGR, &src_obj); - - hr = IWICImagingFactory_CreatePalette(factory, &palette); - ok(hr == S_OK, "CreatePalette error %#x\n", hr); - count = 0xdeadbeef; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 0, "expected 0, got %u\n", count); - - /* NULL palette + Custom type*/ - hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); - ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); - hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, - &GUID_WICPixelFormat24bppBGR, WICBitmapDitherTypeNone, - NULL, 0.0, WICBitmapPaletteTypeCustom); - ok(hr == S_OK, "Initialize error %#x\n", hr); - hr = IWICFormatConverter_CopyPalette(converter, palette); - ok(hr == 0xdeadbeef, "unexpected error %#x\n", hr); - hr = IWICFormatConverter_CopyPixels(converter, NULL, 32 * 3, sizeof(buf), buf); - ok(hr == S_OK, "CopyPixels error %#x\n", hr); - IWICFormatConverter_Release(converter); - - /* NULL palette + Custom type*/ - hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); - ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); - hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, - &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone, - NULL, 0.0, WICBitmapPaletteTypeCustom); - ok(hr == E_INVALIDARG, "unexpected error %#x\n", hr); - hr = IWICFormatConverter_CopyPalette(converter, palette); - ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr); - hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf); - ok(hr == WINCODEC_ERR_WRONGSTATE, "unexpected error %#x\n", hr); - IWICFormatConverter_Release(converter); - - /* empty palette + Custom type*/ - hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); - ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); - hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, - &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone, - palette, 0.0, WICBitmapPaletteTypeCustom); - ok(hr == S_OK, "Initialize error %#x\n", hr); - hr = IWICFormatConverter_CopyPalette(converter, palette); - ok(hr == S_OK, "CopyPalette error %#x\n", hr); - count = 0xdeadbeef; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 0, "expected 0, got %u\n", count); - memset(buf, 0xaa, sizeof(buf)); - hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf); - ok(hr == S_OK, "CopyPixels error %#x\n", hr); - count = 0; - for (i = 0; i < 32 * 2; i++) - if (buf[i] != 0) count++; - ok(count == 0, "expected 0\n"); - IWICFormatConverter_Release(converter); - - /* NULL palette + Predefined type*/ - hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); - ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); - hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, - &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone, - NULL, 0.0, WICBitmapPaletteTypeFixedGray16); - ok(hr == S_OK, "Initialize error %#x\n", hr); - hr = IWICFormatConverter_CopyPalette(converter, palette); - ok(hr == S_OK, "CopyPalette error %#x\n", hr); - count = 0xdeadbeef; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 16, "expected 16, got %u\n", count); - hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf); - ok(hr == S_OK, "CopyPixels error %#x\n", hr); - count = 0; - for (i = 0; i < 32 * 2; i++) - if (buf[i] != 0) count++; - ok(count != 0, "expected != 0\n"); - IWICFormatConverter_Release(converter); - - /* not empty palette + Predefined type*/ - hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); - ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); - hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, - &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone, - palette, 0.0, WICBitmapPaletteTypeFixedHalftone64); - ok(hr == S_OK, "Initialize error %#x\n", hr); - hr = IWICFormatConverter_CopyPalette(converter, palette); - ok(hr == S_OK, "CopyPalette error %#x\n", hr); - count = 0xdeadbeef; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 16, "expected 16, got %u\n", count); - hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf); - ok(hr == S_OK, "CopyPixels error %#x\n", hr); - count = 0; - for (i = 0; i < 32 * 2; i++) - if (buf[i] != 0) count++; - ok(count != 0, "expected != 0\n"); - IWICFormatConverter_Release(converter); - - /* not empty palette + MedianCut type*/ - hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); - ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); - hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, - &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone, - palette, 0.0, WICBitmapPaletteTypeMedianCut); - ok(hr == S_OK, "Initialize error %#x\n", hr); - hr = IWICFormatConverter_CopyPalette(converter, palette); - ok(hr == S_OK, "CopyPalette error %#x\n", hr); - count = 0xdeadbeef; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 16, "expected 16, got %u\n", count); - hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf); - ok(hr == S_OK, "CopyPixels error %#x\n", hr); - count = 0; - for (i = 0; i < 32 * 2; i++) - if (buf[i] != 0) count++; - ok(count != 0, "expected != 0\n"); - IWICFormatConverter_Release(converter); - - /* NULL palette + MedianCut type*/ - hr = IWICImagingFactory_CreateFormatConverter(factory, &converter); - ok(hr == S_OK, "CreateFormatConverter error %#x\n", hr); - hr = IWICFormatConverter_Initialize(converter, &src_obj->IWICBitmapSource_iface, - &GUID_WICPixelFormat8bppIndexed, WICBitmapDitherTypeNone, - NULL, 0.0, WICBitmapPaletteTypeMedianCut); - ok(hr == S_OK || broken(hr == E_INVALIDARG) /* XP */, "Initialize error %#x\n", hr); - if (hr == S_OK) - { - hr = IWICFormatConverter_CopyPalette(converter, palette); - ok(hr == S_OK, "CopyPalette error %#x\n", hr); - count = 0xdeadbeef; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 8, "expected 8, got %u\n", count); - hr = IWICFormatConverter_CopyPixels(converter, NULL, 32, sizeof(buf), buf); - ok(hr == S_OK, "CopyPixels error %#x\n", hr); - count = 0; - for (i = 0; i < 32 * 2; i++) - if (buf[i] != 0) count++; - ok(count != 0, "expected != 0\n"); - } - IWICFormatConverter_Release(converter); - - IWICPalette_Release(palette); - DeleteTestBitmap(src_obj); -} - START_TEST(converter) { HRESULT hr; @@ -1791,27 +1144,9 @@ START_TEST(converter) &IID_IWICImagingFactory, (void **)&factory); ok(hr == S_OK, "failed to create factory: %#x\n", hr); - test_converter_8bppIndexed(); - - test_conversion(&testdata_24bppRGB, &testdata_1bppIndexed, "24bppRGB -> 1bppIndexed", TRUE); - test_conversion(&testdata_24bppRGB, &testdata_2bppIndexed, "24bppRGB -> 2bppIndexed", TRUE); - test_conversion(&testdata_24bppRGB, &testdata_4bppIndexed, "24bppRGB -> 4bppIndexed", TRUE); - test_conversion(&testdata_24bppRGB, &testdata_8bppIndexed, "24bppRGB -> 8bppIndexed", FALSE); - - test_conversion(&testdata_BlackWhite, &testdata_8bppIndexed_BW, "BlackWhite -> 8bppIndexed", TRUE); - test_conversion(&testdata_1bppIndexed, &testdata_8bppIndexed_BW, "1bppIndexed -> 8bppIndexed", TRUE); - test_conversion(&testdata_2bppIndexed, &testdata_8bppIndexed_4colors, "2bppIndexed -> 8bppIndexed", TRUE); - test_conversion(&testdata_4bppIndexed, &testdata_8bppIndexed, "4bppIndexed -> 8bppIndexed", TRUE); - test_conversion(&testdata_32bppBGRA, &testdata_32bppBGR, "BGRA -> BGR", FALSE); test_conversion(&testdata_32bppBGR, &testdata_32bppBGRA, "BGR -> BGRA", FALSE); test_conversion(&testdata_32bppBGRA, &testdata_32bppBGRA, "BGRA -> BGRA", FALSE); - test_conversion(&testdata_32bppBGRA80, &testdata_32bppPBGRA, "BGRA -> PBGRA", FALSE); - - test_conversion(&testdata_32bppRGBA, &testdata_32bppRGB, "RGBA -> RGB", FALSE); - test_conversion(&testdata_32bppRGB, &testdata_32bppRGBA, "RGB -> RGBA", FALSE); - test_conversion(&testdata_32bppRGBA, &testdata_32bppRGBA, "RGBA -> RGBA", FALSE); - test_conversion(&testdata_32bppRGBA80, &testdata_32bppPRGBA, "RGBA -> PRGBA", FALSE); test_conversion(&testdata_24bppBGR, &testdata_24bppBGR, "24bppBGR -> 24bppBGR", FALSE); test_conversion(&testdata_24bppBGR, &testdata_24bppRGB, "24bppBGR -> 24bppRGB", FALSE); @@ -1834,50 +1169,36 @@ START_TEST(converter) test_invalid_conversion(); test_default_converter(); - test_encoder(&testdata_8bppIndexed, &CLSID_WICGifEncoder, - &testdata_8bppIndexed, &CLSID_WICGifDecoder, "GIF encoder 8bppIndexed"); - test_encoder(&testdata_BlackWhite, &CLSID_WICPngEncoder, &testdata_BlackWhite, &CLSID_WICPngDecoder, "PNG encoder BlackWhite"); test_encoder(&testdata_1bppIndexed, &CLSID_WICPngEncoder, &testdata_1bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 1bppIndexed"); - test_encoder(&testdata_2bppIndexed, &CLSID_WICPngEncoder, - &testdata_2bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 2bppIndexed"); - test_encoder(&testdata_4bppIndexed, &CLSID_WICPngEncoder, - &testdata_4bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 4bppIndexed"); test_encoder(&testdata_8bppIndexed, &CLSID_WICPngEncoder, &testdata_8bppIndexed, &CLSID_WICPngDecoder, "PNG encoder 8bppIndexed"); test_encoder(&testdata_24bppBGR, &CLSID_WICPngEncoder, &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 24bppBGR"); + if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */ { - test_encoder(&testdata_32bppBGR, &CLSID_WICPngEncoder, - &testdata_24bppBGR, &CLSID_WICPngDecoder, "PNG encoder 32bppBGR"); -} - test_encoder(&testdata_BlackWhite, &CLSID_WICBmpEncoder, &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder BlackWhite"); test_encoder(&testdata_1bppIndexed, &CLSID_WICBmpEncoder, &testdata_1bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 1bppIndexed"); - test_encoder(&testdata_2bppIndexed, &CLSID_WICBmpEncoder, - &testdata_2bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 2bppIndexed"); - test_encoder(&testdata_4bppIndexed, &CLSID_WICBmpEncoder, - &testdata_4bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 4bppIndexed"); test_encoder(&testdata_8bppIndexed, &CLSID_WICBmpEncoder, &testdata_8bppIndexed, &CLSID_WICBmpDecoder, "BMP encoder 8bppIndexed"); +} test_encoder(&testdata_32bppBGR, &CLSID_WICBmpEncoder, &testdata_32bppBGR, &CLSID_WICBmpDecoder, "BMP encoder 32bppBGR"); test_encoder(&testdata_BlackWhite, &CLSID_WICTiffEncoder, &testdata_BlackWhite, &CLSID_WICTiffDecoder, "TIFF encoder BlackWhite"); +if (!strcmp(winetest_platform, "windows")) /* FIXME: enable once implemented in Wine */ +{ test_encoder(&testdata_1bppIndexed, &CLSID_WICTiffEncoder, &testdata_1bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 1bppIndexed"); - test_encoder(&testdata_2bppIndexed, &CLSID_WICTiffEncoder, - &testdata_2bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 2bppIndexed"); - test_encoder(&testdata_4bppIndexed, &CLSID_WICTiffEncoder, - &testdata_4bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 4bppIndexed"); test_encoder(&testdata_8bppIndexed, &CLSID_WICTiffEncoder, &testdata_8bppIndexed, &CLSID_WICTiffDecoder, "TIFF encoder 8bppIndexed"); +} test_encoder(&testdata_24bppBGR, &CLSID_WICTiffEncoder, &testdata_24bppBGR, &CLSID_WICTiffDecoder, "TIFF encoder 24bppBGR"); diff --git a/modules/rostests/winetests/windowscodecs/palette.c b/modules/rostests/winetests/windowscodecs/palette.c index 46d3bc8343..9031556f53 100644 --- a/modules/rostests/winetests/windowscodecs/palette.c +++ b/modules/rostests/winetests/windowscodecs/palette.c @@ -1,6 +1,6 @@ /* * Copyright 2009 Vincent Povirk for CodeWeavers - * Copyright 2012,2016 Dmitry Timoshkov + * Copyright 2012 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -19,10 +19,9 @@ #include "precomp.h" -static IWICImagingFactory *factory; - static void test_custom_palette(void) { + IWICImagingFactory *factory; IWICPalette *palette, *palette2; HRESULT hr; WICBitmapPaletteType type=0xffffffff; @@ -31,6 +30,11 @@ static void test_custom_palette(void) WICColor colors[4]; BOOL boolresult; + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICImagingFactory, (void**)&factory); + ok(SUCCEEDED(hr), "CoCreateInstance failed, hr=%x\n", hr); + if (FAILED(hr)) return; + hr = IWICImagingFactory_CreatePalette(factory, &palette); ok(SUCCEEDED(hr), "CreatePalette failed, hr=%x\n", hr); if (SUCCEEDED(hr)) @@ -195,6 +199,8 @@ static void test_custom_palette(void) IWICPalette_Release(palette2); IWICPalette_Release(palette); } + + IWICImagingFactory_Release(factory); } static void generate_gray16_palette(DWORD *entries, UINT count) @@ -437,6 +443,7 @@ static void test_predefined_palette(void) { WICBitmapPaletteTypeFixedHalftone256, 0, 0, 256, { 0 } }, { WICBitmapPaletteTypeFixedHalftone256, 0, 0, 256, { 0 }, 1 } }; + IWICImagingFactory *factory; IWICPalette *palette; HRESULT hr; WICBitmapPaletteType type; @@ -444,6 +451,10 @@ static void test_predefined_palette(void) BOOL bret; WICColor color[256]; + hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, + &IID_IWICImagingFactory, (void **)&factory); + ok(hr == S_OK, "CoCreateInstance error %#x\n", hr); + hr = IWICImagingFactory_CreatePalette(factory, &palette); ok(hr == S_OK, "CreatePalette error %#x\n", hr); hr = IWICPalette_InitializePredefined(palette, WICBitmapPaletteTypeCustom, FALSE); @@ -519,136 +530,16 @@ static void test_predefined_palette(void) IWICPalette_Release(palette); } -} - -static BYTE *init_bitmap(UINT *width, UINT *height, UINT *stride) -{ - BYTE *src; - UINT i, j, scale; - - *width = 256; - *height = 256; - *stride = (*width * 3 + 3) & ~3; - trace("width %d, height %d, stride %d\n", *width, *height, *stride); - - src = HeapAlloc(GetProcessHeap(), 0, *stride * *height); - - scale = 256 / *width; - if (!scale) scale = 1; - - for (i = 0; i < *height; i++) - { - for (j = 0; j < *width; j++) - { - src[i * *stride + j*3 + 0] = scale * i; - src[i * *stride + j*3 + 1] = scale * (255 - (i+j)/2); - src[i * *stride + j*3 + 2] = scale * j; - } - } - - return src; -} - -static void test_palette_from_bitmap(void) -{ - HRESULT hr; - BYTE *data; - IWICBitmap *bitmap; - IWICPalette *palette; - WICBitmapPaletteType type; - UINT width, height, stride, count, ret; - WICColor color[257]; - - data = init_bitmap(&width, &height, &stride); - - hr = IWICImagingFactory_CreateBitmapFromMemory(factory, width, height, &GUID_WICPixelFormat24bppRGB, - stride, stride * height, data, &bitmap); - ok(hr == S_OK, "CreateBitmapFromMemory error %#x\n", hr); - - hr = IWICImagingFactory_CreatePalette(factory, &palette); - ok(hr == S_OK, "CreatePalette error %#x\n", hr); - - hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 0, FALSE); - ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); - - hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 1, FALSE); - ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); - - hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 257, FALSE); - ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); - - hr = IWICPalette_InitializeFromBitmap(palette, NULL, 16, FALSE); - ok(hr == E_INVALIDARG, "expected E_INVALIDARG, got %#x\n", hr); - - hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 2, FALSE); - ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); - count = 0; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 2, "expected 2, got %u\n", count); - - hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 2, TRUE); - ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); - count = 0; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 2, "expected 2, got %u\n", count); - - /* without trasparent color */ - hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, FALSE); - ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); - type = -1; - hr = IWICPalette_GetType(palette, &type); - ok(hr == S_OK, "GetType error %#x\n", hr); - ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type); - count = 0; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 16, "expected 16, got %u\n", count); - memset(color, 0, sizeof(color)); - hr = IWICPalette_GetColors(palette, count, color, &ret); - ok(hr == S_OK, "GetColors error %#x\n", hr); - ok(ret == count, "expected %u, got %u\n", count, ret); - ok(color[count - 1] != 0, "expected !0, got %08x\n", color[count - 1]); - - /* with trasparent color */ - hr = IWICPalette_InitializeFromBitmap(palette, (IWICBitmapSource *)bitmap, 16, TRUE); - ok(hr == S_OK, "InitializeFromBitmap error %#x\n", hr); - type = -1; - hr = IWICPalette_GetType(palette, &type); - ok(hr == S_OK, "GetType error %#x\n", hr); - ok(type == WICBitmapPaletteTypeCustom, "expected WICBitmapPaletteTypeCustom, got %#x\n", type); - count = 0; - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 16, "expected 16, got %u\n", count); - memset(color, 0xff, sizeof(color)); - hr = IWICPalette_GetColors(palette, count, color, &ret); - ok(hr == S_OK, "GetColors error %#x\n", hr); - ok(ret == count, "expected %u, got %u\n", count, ret); - ok(color[count - 1] == 0, "expected 0, got %08x\n", color[count - 1]); - - IWICPalette_Release(palette); - IWICBitmap_Release(bitmap); - HeapFree(GetProcessHeap(), 0, data); + IWICImagingFactory_Release(factory); } START_TEST(palette) { - HRESULT hr; - CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); - hr = CoCreateInstance(&CLSID_WICImagingFactory, NULL, CLSCTX_INPROC_SERVER, - &IID_IWICImagingFactory, (void **)&factory); - ok(hr == S_OK, "CoCreateInstance error %#x\n", hr); - test_custom_palette(); test_predefined_palette(); - test_palette_from_bitmap(); - - IWICImagingFactory_Release(factory); CoUninitialize(); } diff --git a/modules/rostests/winetests/windowscodecs/pngformat.c b/modules/rostests/winetests/windowscodecs/pngformat.c index 95ead41324..22f77936c7 100644 --- a/modules/rostests/winetests/windowscodecs/pngformat.c +++ b/modules/rostests/winetests/windowscodecs/pngformat.c @@ -668,11 +668,11 @@ static void test_color_formats(void) { 24, 2, NULL, NULL, NULL }, { 32, 2, NULL, NULL, NULL }, /* 0 - PNG_COLOR_TYPE_GRAY */ - { 1, 0, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat1bppIndexed, TRUE }, - { 2, 0, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppIndexed, TRUE }, - { 4, 0, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppIndexed, TRUE }, - { 8, 0, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppIndexed, TRUE }, - { 16, 0, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat64bppRGBA, TRUE }, + { 1, 0, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat1bppIndexed }, + { 2, 0, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppGray, &GUID_WICPixelFormat2bppIndexed }, + { 4, 0, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat4bppIndexed }, + { 8, 0, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppGray, &GUID_WICPixelFormat8bppIndexed }, + { 16, 0, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat16bppGray, &GUID_WICPixelFormat64bppRGBA }, { 24, 0, NULL, NULL, NULL }, { 32, 0, NULL, NULL, NULL }, /* 3 - PNG_COLOR_TYPE_PALETTE */ @@ -720,6 +720,7 @@ static void test_color_formats(void) hr = create_decoder(buf, sizeof(buf), &decoder); if (!is_valid_png_type_depth(td[i].color_type, td[i].bit_depth, TRUE)) +todo_wine ok(hr == WINCODEC_ERR_UNKNOWNIMAGEFORMAT, "%d: wrong error %#x\n", i, hr); else todo_wine_if(td[i].todo_load) @@ -748,6 +749,7 @@ next_1: hr = create_decoder(buf, sizeof(buf), &decoder); if (!is_valid_png_type_depth(td[i].color_type, td[i].bit_depth, TRUE)) +todo_wine ok(hr == WINCODEC_ERR_UNKNOWNIMAGEFORMAT, "%d: wrong error %#x\n", i, hr); else todo_wine_if(td[i].todo_load) @@ -776,6 +778,7 @@ next_2: hr = create_decoder(buf, sizeof(buf), &decoder); if (!is_valid_png_type_depth(td[i].color_type, td[i].bit_depth, FALSE)) +todo_wine ok(hr == WINCODEC_ERR_UNKNOWNIMAGEFORMAT, "%d: wrong error %#x\n", i, hr); else todo_wine_if(td[i].todo_load) @@ -803,6 +806,7 @@ next_3: hr = create_decoder(buf, sizeof(buf), &decoder); if (!is_valid_png_type_depth(td[i].color_type, td[i].bit_depth, FALSE)) +todo_wine ok(hr == WINCODEC_ERR_UNKNOWNIMAGEFORMAT, "%d: wrong error %#x\n", i, hr); else todo_wine_if(td[i].todo_load) diff --git a/modules/rostests/winetests/windowscodecs/tiffformat.c b/modules/rostests/winetests/windowscodecs/tiffformat.c index 81bd6409e0..e529a44a58 100644 --- a/modules/rostests/winetests/windowscodecs/tiffformat.c +++ b/modules/rostests/winetests/windowscodecs/tiffformat.c @@ -1,5 +1,5 @@ /* - * Copyright 2012,2016 Dmitry Timoshkov + * Copyright 2012 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -31,7 +31,7 @@ #define IFD_FLOAT 11 #define IFD_DOUBLE 12 -#include <pshpack2.h> +#include "pshpack2.h" struct IFD_entry { SHORT id; @@ -127,49 +127,6 @@ static const struct tiff_8bpp_alpha { 96, 1 }, { 0x11,0x22,0x33,0x44,0x55,0x66,0x77,0x88 } }; - -static const struct tiff_8bpp_data -{ - USHORT byte_order; - USHORT version; - ULONG dir_offset; - USHORT number_of_entries; - struct IFD_entry entry[14]; - ULONG next_IFD; - struct IFD_rational res; - short palette_data[3][256]; - BYTE pixel_data[4]; -} tiff_8bpp_data = -{ -#ifdef WORDS_BIGENDIAN - 'M' | 'M' << 8, -#else - 'I' | 'I' << 8, -#endif - 42, - FIELD_OFFSET(struct tiff_8bpp_data, number_of_entries), - 14, - { - { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */ - { 0x100, IFD_LONG, 1, 4 }, /* IMAGEWIDTH */ - { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */ - { 0x102, IFD_SHORT, 1, 8 }, /* BITSPERSAMPLE: XP doesn't accept IFD_LONG here */ - { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */ - { 0x106, IFD_SHORT, 1, 3 }, /* PHOTOMETRIC */ - { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_8bpp_data, pixel_data) }, /* STRIPOFFSETS */ - { 0x115, IFD_SHORT, 1, 1 }, /* SAMPLESPERPIXEL */ - { 0x116, IFD_LONG, 1, 1 }, /* ROWSPERSTRIP */ - { 0x117, IFD_LONG, 1, 1 }, /* STRIPBYTECOUNT */ - { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_8bpp_data, res) }, - { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_8bpp_data, res) }, - { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */ - { 0x140, IFD_SHORT, 256*3, FIELD_OFFSET(struct tiff_8bpp_data, palette_data) } /* COLORMAP */ - }, - 0, - { 96, 1 }, - { { 0 } }, - { 0,1,2,3 } -}; #include "poppack.h" static IWICImagingFactory *factory; @@ -195,96 +152,29 @@ static IStream *create_stream(const void *data, int data_size) return stream; } -static HRESULT create_decoder(const void *image_data, UINT image_size, IWICBitmapDecoder **decoder) +static IWICBitmapDecoder *create_decoder(const void *image_data, UINT image_size) { - HGLOBAL hmem; - BYTE *data; HRESULT hr; IStream *stream; - GUID format; - LONG refcount; - - *decoder = NULL; - - hmem = GlobalAlloc(0, image_size); - data = GlobalLock(hmem); - memcpy(data, image_data, image_size); - GlobalUnlock(hmem); + IWICBitmapDecoder *decoder = NULL; + GUID guid; - hr = CreateStreamOnHGlobal(hmem, TRUE, &stream); - ok(hr == S_OK, "CreateStreamOnHGlobal error %#x\n", hr); - - hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, decoder); - if (hr == S_OK) - { - hr = IWICBitmapDecoder_GetContainerFormat(*decoder, &format); - ok(hr == S_OK, "GetContainerFormat error %#x\n", hr); - ok(IsEqualGUID(&format, &GUID_ContainerFormatTiff), - "wrong container format %s\n", wine_dbgstr_guid(&format)); + stream = create_stream(image_data, image_size); - refcount = IStream_Release(stream); - ok(refcount > 0, "expected stream refcount > 0\n"); - } - - return hr; -} - -static HRESULT get_pixelformat_info(const GUID *format, UINT *bpp, UINT *channels, BOOL *trasparency) -{ - HRESULT hr; - IWICComponentInfo *info; - IWICPixelFormatInfo2 *formatinfo; - - hr = IWICImagingFactory_CreateComponentInfo(factory, format, &info); - ok(hr == S_OK, "CreateComponentInfo(%s) error %#x\n", wine_dbgstr_guid(format), hr); - if (hr == S_OK) - { - hr = IWICComponentInfo_QueryInterface(info, &IID_IWICPixelFormatInfo2, (void **)&formatinfo); - if (hr == S_OK) - { - hr = IWICPixelFormatInfo2_SupportsTransparency(formatinfo, trasparency); - ok(hr == S_OK, "SupportsTransparency error %#x\n", hr); - IWICPixelFormatInfo2_Release(formatinfo); - } - hr = IWICComponentInfo_QueryInterface(info, &IID_IWICPixelFormatInfo, (void **)&formatinfo); - if (hr == S_OK) - { - hr = IWICPixelFormatInfo2_GetBitsPerPixel(formatinfo, bpp); - ok(hr == S_OK, "GetBitsPerPixel error %#x\n", hr); - hr = IWICPixelFormatInfo2_GetChannelCount(formatinfo, channels); - ok(hr == S_OK, "GetChannelCount error %#x\n", hr); - IWICPixelFormatInfo2_Release(formatinfo); - } - IWICComponentInfo_Release(info); - } - return hr; -} + hr = IWICImagingFactory_CreateDecoderFromStream(factory, stream, NULL, 0, &decoder); + ok(hr == S_OK, "CreateDecoderFromStream error %#x\n", hr); + if (FAILED(hr)) return NULL; -static void dump_tiff(void *buf) -{ - UINT count, i; - struct tiff_1bpp_data *tiff; - struct IFD_entry *tag; + hr = IWICBitmapDecoder_GetContainerFormat(decoder, &guid); + ok(hr == S_OK, "GetContainerFormat error %#x\n", hr); + ok(IsEqualGUID(&guid, &GUID_ContainerFormatTiff), "container format is not TIFF\n"); - tiff = buf; - count = *(short *)((char *)tiff + tiff->dir_offset); - tag = (struct IFD_entry *)((char *)tiff + tiff->dir_offset + sizeof(short)); + IStream_Release(stream); - for (i = 0; i < count; i++) - { - printf("tag %u: id %04x, type %04x, count %u, value %d", - i, tag[i].id, tag[i].type, tag[i].count, tag[i].value); - if (tag[i].id == 0x102 && tag[i].count > 2) - { - short *bps = (short *)((char *)tiff + tag[i].value); - printf(" (%d,%d,%d,%d)\n", bps[0], bps[1], bps[2], bps[3]); - } - else - printf("\n"); - } + return decoder; } -static void test_tiff_1bpp_palette(void) +static void test_tiff_palette(void) { HRESULT hr; IWICBitmapDecoder *decoder; @@ -292,9 +182,9 @@ static void test_tiff_1bpp_palette(void) IWICPalette *palette; GUID format; - hr = create_decoder(&tiff_1bpp_data, sizeof(tiff_1bpp_data), &decoder); - ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr); - if (hr != S_OK) return; + decoder = create_decoder(&tiff_1bpp_data, sizeof(tiff_1bpp_data)); + ok(decoder != 0, "Failed to load TIFF image data\n"); + if (!decoder) return; hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); ok(hr == S_OK, "GetFrame error %#x\n", hr); @@ -426,9 +316,9 @@ static void test_tiff_8bpp_alpha(void) static const BYTE expected_data[16] = { 0x11,0x11,0x11,0x22,0x33,0x33,0x33,0x44, 0x55,0x55,0x55,0x66,0x77,0x77,0x77,0x88 }; - hr = create_decoder(&tiff_8bpp_alpha, sizeof(tiff_8bpp_alpha), &decoder); - ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr); - if (hr != S_OK) return; + decoder = create_decoder(&tiff_8bpp_alpha, sizeof(tiff_8bpp_alpha)); + ok(decoder != 0, "Failed to load TIFF image data\n"); + if (!decoder) return; hr = IWICBitmapDecoder_GetFrameCount(decoder, &frame_count); ok(hr == S_OK, "GetFrameCount error %#x\n", hr); @@ -473,464 +363,6 @@ static void test_tiff_8bpp_alpha(void) IWICBitmapDecoder_Release(decoder); } -static void generate_tiff_palette(void *buf, unsigned count) -{ - unsigned short *r, *g, *b; - unsigned i; - - r = buf; - g = r + count; - b = g + count; - - r[0] = 0x11 * 257; - g[0] = 0x22 * 257; - b[0] = 0x33 * 257; - r[1] = 0x44 * 257; - g[1] = 0x55 * 257; - b[1] = 0x66 * 257; - r[2] = 0x77 * 257; - g[2] = 0x88 * 257; - b[2] = 0x99 * 257; - r[3] = 0xa1 * 257; - g[3] = 0xb5 * 257; - b[3] = 0xff * 257; - - for (i = 4; i < count; i++) - { - r[i] = i * 257; - g[i] = (i | 0x40) * 257; - b[i] = (i | 0x80) * 257; - } -} - -static void test_tiff_8bpp_palette(void) -{ - char buf[sizeof(tiff_8bpp_data)]; - HRESULT hr; - IWICBitmapDecoder *decoder; - IWICBitmapFrameDecode *frame; - IWICPalette *palette; - GUID format; - UINT count, ret; - WICColor color[256]; - - memcpy(buf, &tiff_8bpp_data, sizeof(tiff_8bpp_data)); - generate_tiff_palette(buf + FIELD_OFFSET(struct tiff_8bpp_data, palette_data), 256); - - hr = create_decoder(buf, sizeof(buf), &decoder); - ok(hr == S_OK, "Failed to load TIFF image data %#x\n", hr); - if (hr != S_OK) return; - - hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); - ok(hr == S_OK, "GetFrame error %#x\n", hr); - - hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format); - ok(hr == S_OK, "GetPixelFormat error %#x\n", hr); - ok(IsEqualGUID(&format, &GUID_WICPixelFormat8bppIndexed), - "expected GUID_WICPixelFormat8bppIndexed, got %s\n", wine_dbgstr_guid(&format)); - - hr = IWICImagingFactory_CreatePalette(factory, &palette); - ok(hr == S_OK, "CreatePalette error %#x\n", hr); - hr = IWICBitmapFrameDecode_CopyPalette(frame, palette); - ok(hr == S_OK, "CopyPalette error %#x\n", hr); - - hr = IWICPalette_GetColorCount(palette, &count); - ok(hr == S_OK, "GetColorCount error %#x\n", hr); - ok(count == 256, "expected 256, got %u\n", count); - - hr = IWICPalette_GetColors(palette, 256, color, &ret); - ok(hr == S_OK, "GetColors error %#x\n", hr); - ok(ret == count, "expected %u, got %u\n", count, ret); - ok(color[0] == 0xff112233, "got %#x\n", color[0]); - ok(color[1] == 0xff445566, "got %#x\n", color[1]); - ok(color[2] == 0xff778899, "got %#x\n", color[2]); - ok(color[3] == 0xffa1b5ff, "got %#x\n", color[3]); - - IWICPalette_Release(palette); - IWICBitmapFrameDecode_Release(frame); - IWICBitmapDecoder_Release(decoder); -} - -#include "pshpack2.h" -static const struct tiff_1x1_data -{ - USHORT byte_order; - USHORT version; - ULONG dir_offset; - USHORT number_of_entries; - struct IFD_entry entry[12]; - ULONG next_IFD; - struct IFD_rational res; - short palette_data[3][256]; - short bps_data[4]; - BYTE pixel_data[32]; -} tiff_1x1_data = -{ -#ifdef WORDS_BIGENDIAN - 'M' | 'M' << 8, -#else - 'I' | 'I' << 8, -#endif - 42, - FIELD_OFFSET(struct tiff_1x1_data, number_of_entries), - 12, - { - { 0xff, IFD_SHORT, 1, 0 }, /* SUBFILETYPE */ - { 0x100, IFD_LONG, 1, 1 }, /* IMAGEWIDTH */ - { 0x101, IFD_LONG, 1, 1 }, /* IMAGELENGTH */ - { 0x102, IFD_SHORT, 3, FIELD_OFFSET(struct tiff_1x1_data, bps_data) }, /* BITSPERSAMPLE */ - { 0x103, IFD_SHORT, 1, 1 }, /* COMPRESSION: XP doesn't accept IFD_LONG here */ - { 0x106, IFD_SHORT, 1, 2 }, /* PHOTOMETRIC */ - { 0x111, IFD_LONG, 1, FIELD_OFFSET(struct tiff_1x1_data, pixel_data) }, /* STRIPOFFSETS */ - { 0x115, IFD_SHORT, 1, 3 }, /* SAMPLESPERPIXEL */ - { 0x11a, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) }, - { 0x11b, IFD_RATIONAL, 1, FIELD_OFFSET(struct tiff_1x1_data, res) }, - { 0x128, IFD_SHORT, 1, 2 }, /* RESOLUTIONUNIT */ - { 0x140, IFD_SHORT, 256*3, FIELD_OFFSET(struct tiff_1x1_data, palette_data) } /* COLORMAP */ - }, - 0, - { 96, 1 }, - { { 0 } }, - { 8,8,8,0 }, - { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 } -}; -#include "poppack.h" - -static UINT width_bytes(UINT width, UINT bpp) -{ - return (width * bpp + 7) / 8; -} - -static void test_color_formats(void) -{ - struct bitmap_data - { - UINT bpp; - UINT width; - UINT height; - const WICPixelFormatGUID *format; - const BYTE *bits; - }; - static const BYTE bits_1bpsBGR[] = { 0,255,0,255,0,255,255,255,0,0,0,255,255,0,0,0,255,255,255,255,255,0,0,0,0,255,0,255,0,255 }; - static const struct bitmap_data data_1bpsBGR = - { - 24, 10, 2, &GUID_WICPixelFormat24bppBGR, bits_1bpsBGR - }; - static const BYTE bits_4bpsBGR[] = { 204,85,85,136,187,51,0,85,85,85,0,68,0,102,0,136,0,119,0,153,0 }; - static const struct bitmap_data data_4bpsBGR = - { - 24, 5, 2, &GUID_WICPixelFormat24bppBGR, bits_4bpsBGR - }; - static const BYTE bits_8bpsBGR[] = { 2,0,1,5,4,3,8,7,6 }; - static const struct bitmap_data data_8bpsBGR = - { - 24, 3, 1, &GUID_WICPixelFormat24bppBGR, bits_8bpsBGR - }; - static const BYTE bits_48bppRGB[] = { 1,0,2,3,4,5,6,7,8,9,0,1 }; - static const struct bitmap_data data_48bppRGB = - { - 48, 2, 1, &GUID_WICPixelFormat48bppRGB, bits_48bppRGB - }; - static const BYTE bits_1bpsBGRA[] = { 0,255,0,255,0,255,0,255,0,255,255,0,255,0,0,255,255,0,255,255,0,0,255,0,0,255,0,255,0,255,0,255,0,0,0,0,0,255,0,0 }; - static const struct bitmap_data data_1bpsBGRA = - { - 32, 5, 2, &GUID_WICPixelFormat32bppBGRA, bits_1bpsBGRA - }; - static const BYTE bits_4bpsBGRA[] = { 204,85,85,51,85,136,187,85,0,68,0,85,0,102,0,119,0,136,0,153,0,0,0,17,0,34,0,51 }; - static const struct bitmap_data data_4bpsBGRA = - { - 32, 5, 2, &GUID_WICPixelFormat32bppBGRA, bits_4bpsBGRA - }; - static const BYTE bits_8bpsBGRA[] = { 2,0,1,3,6,5,4,7,0,9,8,1,4,3,2,5 }; - static const struct bitmap_data data_8bpsBGRA = - { - 32, 4, 1, &GUID_WICPixelFormat32bppBGRA, bits_8bpsBGRA - }; - static const BYTE bits_64bppRGBA[] = { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 }; - static const struct bitmap_data data_64bppRGBA = - { - 64, 2, 1, &GUID_WICPixelFormat64bppRGBA, bits_64bppRGBA - }; - static const BYTE bits_BlackWhite[] = { 85,195,184,85 }; - static const struct bitmap_data data_BlackWhite = - { - 1, 30, 1, &GUID_WICPixelFormatBlackWhite, bits_BlackWhite - }; - static const BYTE bits_BlackWhite_xp[] = { 85,195,184,84 }; - static const struct bitmap_data data_BlackWhite_xp = - { - 1, 30, 1, &GUID_WICPixelFormatBlackWhite, bits_BlackWhite_xp - }; - static const BYTE bits_4bppGray[] = { 85,195,184,85 }; - static const struct bitmap_data data_4bppGray = - { - 4, 7, 1, &GUID_WICPixelFormat4bppGray, bits_4bppGray - }; - static const BYTE bits_4bppGray_xp[] = { 85,195,184,80 }; - static const struct bitmap_data data_4bppGray_xp = - { - 4, 7, 1, &GUID_WICPixelFormat4bppGray, bits_4bppGray_xp - }; - static const BYTE bits_8bppGray[] = { 1,0,2,3,4,5,6,7,8,9 }; - static const struct bitmap_data data_8bppGray = - { - 8, 10, 1, &GUID_WICPixelFormat8bppGray, bits_8bppGray - }; - static const BYTE bits_16bppGray[] = { 1,0,2,3,4,5 }; - static const struct bitmap_data data_16bppGray = - { - 16, 3, 1, &GUID_WICPixelFormat16bppGray, bits_16bppGray - }; - static const BYTE bits_32bppGrayFloat[] = { 1,0,2,3,4,5,6,7,8,9,0,1 }; - static const struct bitmap_data data_32bppGrayFloat = - { - 32, 3, 1, &GUID_WICPixelFormat32bppGrayFloat, bits_32bppGrayFloat - }; -#if 0 /* FIXME */ - static const BYTE bits_96bpp3Channels[] = { 0 }; - static const struct bitmap_data data_96bpp3Channels = - { - 64, 1, 1, &GUID_WICPixelFormat96bpp3Channels, bits_96bpp3Channels - }; -#endif - static const BYTE bits_128bppRGBAFloat[] = { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 }; - static const struct bitmap_data data_128bppRGBAFloat = - { - 128, 1, 1, &GUID_WICPixelFormat128bppRGBAFloat, bits_128bppRGBAFloat - }; - static const BYTE bits_1bppIndexed[] = { 85,195,184,85 }; - static const struct bitmap_data data_1bppIndexed = - { - 1, 32, 1, &GUID_WICPixelFormat1bppIndexed, bits_1bppIndexed - }; - static const BYTE bits_4bppIndexed[] = { 85,195,184,85 }; - static const struct bitmap_data data_4bppIndexed = - { - 4, 7, 1, &GUID_WICPixelFormat4bppIndexed, bits_4bppIndexed - }; - static const BYTE bits_4bppIndexed_xp[] = { 85,195,184,80 }; - static const struct bitmap_data data_4bppIndexed_xp = - { - 4, 7, 1, &GUID_WICPixelFormat4bppIndexed, bits_4bppIndexed_xp - }; - static const BYTE bits_8bppIndexed[] = { 1,0,2,3,4,5,6,7,8,9 }; - static const struct bitmap_data data_8bppIndexed = - { - 8, 3, 1, &GUID_WICPixelFormat8bppIndexed, bits_8bppIndexed - }; - static const BYTE bits_32bppCMYK[] = { 1,0,2,3,4,5,6,7,8,9,0,1 }; - static const struct bitmap_data data_32bppCMYK = - { - 32, 3, 1, &GUID_WICPixelFormat32bppCMYK, bits_32bppCMYK - }; - static const BYTE bits_64bppCMYK[] = { 1,0,2,3,4,5,6,7,8,9,0,1,2,3,4,5 }; - static const struct bitmap_data data_64bppCMYK = - { - 64, 2, 1, &GUID_WICPixelFormat64bppCMYK, bits_64bppCMYK - }; - static const struct - { - int photometric; /* PhotometricInterpretation */ - int samples; /* SamplesPerPixel */ - int bps; /* BitsPerSample */ - const struct bitmap_data *data; - const struct bitmap_data *alt_data; - } td[] = - { - /* 2 - RGB */ - { 2, 3, 1, &data_1bpsBGR }, - { 2, 3, 4, &data_4bpsBGR }, - { 2, 3, 8, &data_8bpsBGR }, - { 2, 3, 16, &data_48bppRGB }, - { 2, 3, 24, NULL }, -#if 0 /* FIXME */ - { 2, 3, 32, &data_96bpp3Channels }, -#endif - { 2, 4, 1, &data_1bpsBGRA }, - { 2, 4, 4, &data_4bpsBGRA }, - { 2, 4, 8, &data_8bpsBGRA }, - { 2, 4, 16, &data_64bppRGBA }, - { 2, 4, 24, NULL }, - { 2, 4, 32, &data_128bppRGBAFloat }, - /* 1 - BlackIsZero (Bilevel) */ - { 1, 1, 1, &data_BlackWhite, &data_BlackWhite_xp }, - { 1, 1, 4, &data_4bppGray, &data_4bppGray_xp }, - { 1, 1, 8, &data_8bppGray }, - { 1, 1, 16, &data_16bppGray }, - { 1, 1, 24, NULL }, - { 1, 1, 32, &data_32bppGrayFloat }, - /* 3 - Palette Color */ - { 3, 1, 1, &data_1bppIndexed }, - { 3, 1, 4, &data_4bppIndexed, &data_4bppIndexed_xp }, - { 3, 1, 8, &data_8bppIndexed }, -#if 0 /* FIXME: for some reason libtiff replaces photometric 3 by 1 for bps > 8 */ - { 3, 1, 16, &data_8bppIndexed }, - { 3, 1, 24, &data_8bppIndexed }, - { 3, 1, 32, &data_8bppIndexed }, -#endif - /* 5 - Separated */ - { 5, 4, 1, NULL }, - { 5, 4, 4, NULL }, - { 5, 4, 8, &data_32bppCMYK }, - { 5, 4, 16, &data_64bppCMYK }, - { 5, 4, 24, NULL }, - { 5, 4, 32, NULL }, - }; - BYTE buf[sizeof(tiff_1x1_data)]; - BYTE pixels[256]; - HRESULT hr; - IWICBitmapDecoder *decoder; - IWICBitmapFrameDecode *frame; - GUID format; - UINT count, i, bpp, channels, ret; - BOOL trasparency; - struct IFD_entry *tag, *tag_photo = NULL, *tag_bps = NULL, *tag_samples = NULL, *tag_colormap = NULL; - struct IFD_entry *tag_width = NULL, *tag_height = NULL; - short *bps; - - memcpy(buf, &tiff_1x1_data, sizeof(tiff_1x1_data)); - generate_tiff_palette(buf + FIELD_OFFSET(struct tiff_1x1_data, palette_data), 256); - - count = *(short *)(buf + tiff_1x1_data.dir_offset); - tag = (struct IFD_entry *)(buf + tiff_1x1_data.dir_offset + sizeof(short)); - - /* verify the TIFF structure */ - for (i = 0; i < count; i++) - { - if (tag[i].id == 0x100) /* ImageWidth */ - tag_width = &tag[i]; - else if (tag[i].id == 0x101) /* ImageLength */ - tag_height = &tag[i]; - else if (tag[i].id == 0x102) /* BitsPerSample */ - tag_bps = &tag[i]; - else if (tag[i].id == 0x106) /* PhotometricInterpretation */ - tag_photo = &tag[i]; - else if (tag[i].id == 0x115) /* SamplesPerPixel */ - tag_samples = &tag[i]; - else if (tag[i].id == 0x140) /* ColorMap */ - tag_colormap = &tag[i]; - } - - ok(tag_bps && tag_photo && tag_samples && tag_colormap, "tag 0x102,0x106,0x115 or 0x140 is missing\n"); - if (!tag_bps || !tag_photo || !tag_samples || !tag_colormap) return; - - ok(tag_bps->type == IFD_SHORT, "tag 0x102 should have type IFD_SHORT\n"); - bps = (short *)(buf + tag_bps->value); - ok(bps[0] == 8 && bps[1] == 8 && bps[2] == 8 && bps[3] == 0, - "expected bps 8,8,8,0 got %d,%d,%d,%d\n", bps[0], bps[1], bps[2], bps[3]); - - for (i = 0; i < sizeof(td)/sizeof(td[0]); i++) - { - if (td[i].data) - { - bpp = td[i].samples * td[i].bps; - if (winetest_debug > 1) - trace("samples %u, bps %u, bpp %u, width %u => width_bytes %u\n", td[i].samples, td[i].bps, bpp, - td[i].data->width, width_bytes(td[i].data->width, bpp)); - tag_width->value = td[i].data->width; - tag_height->value = td[i].data->height; - } - else - { - tag_width->value = 1; - tag_height->value = 1; - } - - tag_colormap->count = (1 << td[i].bps) * 3; - - if (td[i].bps < 8) - { - buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data)] = 0x55; - buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 1] = 0xc3; - buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 2] = 0xb8; - buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 3] = 0x55; - } - else - { - buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data)] = 1; - buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 1] = 0; - buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 2] = 2; - buf[FIELD_OFFSET(struct tiff_1x1_data, pixel_data) + 3] = 3; - } - - tag_photo->value = td[i].photometric; - tag_bps->count = td[i].samples; - tag_samples->value = td[i].samples; - - if (td[i].samples == 1) - tag_bps->value = td[i].bps; - else if (td[i].samples == 2) - tag_bps->value = MAKELONG(td[i].bps, td[i].bps); - else if (td[i].samples == 3) - { - tag_bps->value = (BYTE *)bps - buf; - bps[0] = bps[1] = bps[2] = td[i].bps; - } - else if (td[i].samples == 4) - { - tag_bps->value = (BYTE *)bps - buf; - bps[0] = bps[1] = bps[2] = bps[3] = td[i].bps; - } - else - { - ok(0, "%u: unsupported samples count %d\n", i, td[i].samples); - continue; - } - - hr = create_decoder(buf, sizeof(buf), &decoder); - if (!td[i].data) - { - ok(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT || hr == WINCODEC_ERR_COMPONENTNOTFOUND /* win8+ */ || WINCODEC_ERR_BADIMAGE /* XP */, - "%u: (%d,%d,%d) wrong error %#x\n", i, td[i].photometric, td[i].samples, td[i].bps, hr); - if (hr == S_OK) - { - IWICBitmapDecoder_Release(decoder); - dump_tiff(buf); - } - continue; - } - else - ok(hr == S_OK || broken(hr == WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT || hr == WINCODEC_ERR_BADIMAGE) /* XP */, - "%u: failed to load TIFF image data (%d,%d,%d) %#x\n", - i, td[i].photometric, td[i].samples, td[i].bps, hr); - if (hr != S_OK) continue; - - hr = IWICBitmapDecoder_GetFrame(decoder, 0, &frame); - ok(hr == S_OK, "%u: GetFrame error %#x\n", i, hr); - - hr = IWICBitmapFrameDecode_GetPixelFormat(frame, &format); - ok(hr == S_OK, "%u: GetPixelFormat error %#x\n", i, hr); - ok(IsEqualGUID(&format, td[i].data->format), - "%u (%d,%d,%d): expected %s, got %s\n", - i, td[i].photometric, td[i].samples, td[i].bps, - wine_dbgstr_guid(td[i].data->format), wine_dbgstr_guid(&format)); - - trasparency = (td[i].photometric == 2 && td[i].samples == 4); /* for XP */ - hr = get_pixelformat_info(&format, &bpp, &channels, &trasparency); - ok(hr == S_OK, "%u: get_pixelformat_bpp error %#x\n", i, hr); - ok(bpp == td[i].data->bpp, "%u: expected %u, got %u\n", i, td[i].data->bpp, bpp); - ok(channels == td[i].samples, "%u: expected %u, got %u\n", i, td[i].samples, channels); - ok(trasparency == (td[i].photometric == 2 && td[i].samples == 4), "%u: got %u\n", i, trasparency); - - memset(pixels, 0, sizeof(pixels)); - hr = IWICBitmapFrameDecode_CopyPixels(frame, NULL, width_bytes(td[i].data->width, bpp), sizeof(pixels), pixels); - ok(hr == S_OK, "%u: CopyPixels error %#x\n", i, hr); - ret = memcmp(pixels, td[i].data->bits, width_bytes(td[i].data->width, bpp)); - if (ret && td[i].alt_data) - ret = memcmp(pixels, td[i].alt_data->bits, width_bytes(td[i].data->width, bpp)); - ok(ret == 0, "%u: (%d,%d,%d) wrong pixel data\n", i, td[i].photometric, td[i].samples, td[i].bps); - if (ret) - { - UINT j, n = width_bytes(td[i].data->width, bpp); - for (j = 0; j < n; j++) - printf("%u%s", pixels[j], (j + 1) < n ? "," : "\n"); - } - - IWICBitmapFrameDecode_Release(frame); - IWICBitmapDecoder_Release(decoder); - } -} - START_TEST(tiffformat) { HRESULT hr; @@ -942,9 +374,7 @@ START_TEST(tiffformat) ok(hr == S_OK, "CoCreateInstance error %#x\n", hr); if (FAILED(hr)) return; - test_color_formats(); - test_tiff_1bpp_palette(); - test_tiff_8bpp_palette(); + test_tiff_palette(); test_QueryCapability(); test_tiff_8bpp_alpha();
6 years, 11 months
1
0
0
0
01/01: [WINDOWSCODECS] Sync with Wine 3.0. CORE-14225
by Amine Khaldi
https://git.reactos.org/?p=reactos.git;a=commitdiff;h=c3715ca58f21624199c9f…
commit c3715ca58f21624199c9f507840e73731887951c Author: Amine Khaldi <amine.khaldi(a)reactos.org> AuthorDate: Sat Jan 20 13:50:46 2018 +0100 Commit: Amine Khaldi <amine.khaldi(a)reactos.org> CommitDate: Sat Jan 20 13:50:46 2018 +0100 [WINDOWSCODECS] Sync with Wine 3.0. CORE-14225 --- dll/win32/windowscodecs/CMakeLists.txt | 11 +- dll/win32/windowscodecs/bitmap.c | 214 +---- dll/win32/windowscodecs/bmpdecode.c | 2 +- dll/win32/windowscodecs/bmpencode.c | 80 +- dll/win32/windowscodecs/clsfactory.c | 1 - dll/win32/windowscodecs/converter.c | 296 +----- dll/win32/windowscodecs/gifformat.c | 1015 +------------------- dll/win32/windowscodecs/imgfactory.c | 115 +-- dll/win32/windowscodecs/info.c | 20 +- dll/win32/windowscodecs/jpegformat.c | 185 ++-- dll/win32/windowscodecs/metadatahandler.c | 47 +- dll/win32/windowscodecs/palette.c | 279 +----- dll/win32/windowscodecs/pngformat.c | 182 ++-- dll/win32/windowscodecs/regsvr.c | 113 +-- dll/win32/windowscodecs/scaler.c | 169 ---- dll/win32/windowscodecs/tiffformat.c | 320 +----- dll/win32/windowscodecs/wincodecs_private.h | 78 +- dll/win32/windowscodecs/windowscodecs.spec | 3 +- dll/win32/windowscodecs/windowscodecs_wincodec.idl | 7 - media/doc/README.WINE | 2 +- 20 files changed, 417 insertions(+), 2722 deletions(-) diff --git a/dll/win32/windowscodecs/CMakeLists.txt b/dll/win32/windowscodecs/CMakeLists.txt index 227552a0b5..7ed058d112 100644 --- a/dll/win32/windowscodecs/CMakeLists.txt +++ b/dll/win32/windowscodecs/CMakeLists.txt @@ -23,6 +23,7 @@ spec2def(windowscodecs.dll windowscodecs.spec ADD_IMPORTLIB) add_rpcproxy_files(windowscodecs_wincodec.idl) list(APPEND SOURCE + bitmap.c bmpdecode.c bmpencode.c clipper.c @@ -52,16 +53,6 @@ list(APPEND SOURCE ungif.c wincodecs_private.h) -if(MSVC) - if(ARCH STREQUAL "i386") - list(APPEND SOURCE msvc-thiscall.c) - endif() - set_source_files_properties(bitmap.c PROPERTIES COMPILE_FLAGS "/FImsvc.h") - list(APPEND ADDITIONAL_SOURCE bitmap.c) -else() - list(APPEND SOURCE bitmap.c) -endif() - list(APPEND ADDITIONAL_SOURCE guid.c version.rc diff --git a/dll/win32/windowscodecs/bitmap.c b/dll/win32/windowscodecs/bitmap.c index 3d5a2bb496..dfd7dda89f 100644 --- a/dll/win32/windowscodecs/bitmap.c +++ b/dll/win32/windowscodecs/bitmap.c @@ -31,7 +31,6 @@ typedef struct BitmapImpl { int palette_set; LONG lock; /* 0 if not locked, -1 if locked for writing, count if locked for reading */ BYTE *data; - BOOL is_section; /* TRUE if data is a section created by an application */ UINT width, height; UINT stride; UINT bpp; @@ -63,13 +62,10 @@ static inline BitmapImpl *impl_from_IMILUnknown1(IMILUnknown1 *iface) return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown1_iface); } -#ifndef __REACTOS__ -/* This is currently unused */ static inline BitmapImpl *impl_from_IMILUnknown2(IMILUnknown2 *iface) { return CONTAINING_RECORD(iface, BitmapImpl, IMILUnknown2_iface); } -#endif static inline BitmapLockImpl *impl_from_IWICBitmapLock(IWICBitmapLock *iface) { @@ -125,7 +121,6 @@ static HRESULT WINAPI BitmapLockImpl_QueryInterface(IWICBitmapLock *iface, REFII } else { - FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -239,14 +234,12 @@ static HRESULT WINAPI BitmapImpl_QueryInterface(IWICBitmap *iface, REFIID iid, { *ppv = &This->IWICBitmap_iface; } - else if (IsEqualIID(&IID_IMILBitmap, iid) || - IsEqualIID(&IID_IMILBitmapSource, iid)) + else if (IsEqualIID(&IID_IMILBitmapSource, iid)) { *ppv = &This->IMILBitmapSource_iface; } else { - FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -277,10 +270,7 @@ static ULONG WINAPI BitmapImpl_Release(IWICBitmap *iface) if (This->palette) IWICPalette_Release(This->palette); This->cs.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->cs); - if (This->is_section) - UnmapViewOfFile(This->data); - else - HeapFree(GetProcessHeap(), 0, This->data); + HeapFree(GetProcessHeap(), 0, This->data); HeapFree(GetProcessHeap(), 0, This); } @@ -475,22 +465,13 @@ static HRESULT WINAPI IMILBitmapImpl_QueryInterface(IMILBitmapSource *iface, REF if (!ppv) return E_INVALIDARG; if (IsEqualIID(&IID_IUnknown, iid) || - IsEqualIID(&IID_IMILBitmap, iid) || IsEqualIID(&IID_IMILBitmapSource, iid)) { IUnknown_AddRef(&This->IMILBitmapSource_iface); *ppv = &This->IMILBitmapSource_iface; return S_OK; } - else if (IsEqualIID(&IID_IWICBitmap, iid) || - IsEqualIID(&IID_IWICBitmapSource, iid)) - { - IUnknown_AddRef(&This->IWICBitmap_iface); - *ppv = &This->IWICBitmap_iface; - return S_OK; - } - FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -511,7 +492,6 @@ static HRESULT WINAPI IMILBitmapImpl_GetSize(IMILBitmapSource *iface, UINT *width, UINT *height) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); - TRACE("(%p,%p,%p)\n", iface, width, height); return IWICBitmap_GetSize(&This->IWICBitmap_iface, width, height); } @@ -565,7 +545,6 @@ static HRESULT WINAPI IMILBitmapImpl_GetPixelFormat(IMILBitmapSource *iface, } } - TRACE("=> %u\n", *format); return S_OK; } @@ -573,7 +552,6 @@ static HRESULT WINAPI IMILBitmapImpl_GetResolution(IMILBitmapSource *iface, double *dpix, double *dpiy) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); - TRACE("(%p,%p,%p)\n", iface, dpix, dpiy); return IWICBitmap_GetResolution(&This->IWICBitmap_iface, dpix, dpiy); } @@ -581,7 +559,6 @@ static HRESULT WINAPI IMILBitmapImpl_CopyPalette(IMILBitmapSource *iface, IWICPalette *palette) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); - TRACE("(%p,%p)\n", iface, palette); return IWICBitmap_CopyPalette(&This->IWICBitmap_iface, palette); } @@ -589,11 +566,10 @@ static HRESULT WINAPI IMILBitmapImpl_CopyPixels(IMILBitmapSource *iface, const WICRect *rc, UINT stride, UINT size, BYTE *buffer) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); - TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer); return IWICBitmap_CopyPixels(&This->IWICBitmap_iface, rc, stride, size, buffer); } -static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmapSource *iface, void **ppv) +static HRESULT WINAPI IMILBitmapImpl_UnknownMethod1(IMILBitmapSource *iface, void **ppv) { BitmapImpl *This = impl_from_IMILBitmapSource(iface); @@ -601,46 +577,12 @@ static HRESULT WINAPI IMILBitmapImpl_unknown1(IMILBitmapSource *iface, void **pp if (!ppv) return E_INVALIDARG; - /* reference count is not incremented here */ + IUnknown_AddRef(&This->IMILUnknown1_iface); *ppv = &This->IMILUnknown1_iface; return S_OK; } -static HRESULT WINAPI IMILBitmapImpl_Lock(IMILBitmapSource *iface, const WICRect *rc, DWORD flags, IWICBitmapLock **lock) -{ - BitmapImpl *This = impl_from_IMILBitmapSource(iface); - TRACE("(%p,%p,%08x,%p)\n", iface, rc, flags, lock); - return IWICBitmap_Lock(&This->IWICBitmap_iface, rc, flags, lock); -} - -static HRESULT WINAPI IMILBitmapImpl_Unlock(IMILBitmapSource *iface, IWICBitmapLock *lock) -{ - TRACE("(%p,%p)\n", iface, lock); - IWICBitmapLock_Release(lock); - return S_OK; -} - -static HRESULT WINAPI IMILBitmapImpl_SetPalette(IMILBitmapSource *iface, IWICPalette *palette) -{ - BitmapImpl *This = impl_from_IMILBitmapSource(iface); - TRACE("(%p,%p)\n", iface, palette); - return IWICBitmap_SetPalette(&This->IWICBitmap_iface, palette); -} - -static HRESULT WINAPI IMILBitmapImpl_SetResolution(IMILBitmapSource *iface, double dpix, double dpiy) -{ - BitmapImpl *This = impl_from_IMILBitmapSource(iface); - TRACE("(%p,%f,%f)\n", iface, dpix, dpiy); - return IWICBitmap_SetResolution(&This->IWICBitmap_iface, dpix, dpiy); -} - -static HRESULT WINAPI IMILBitmapImpl_AddDirtyRect(IMILBitmapSource *iface, const WICRect *rc) -{ - FIXME("(%p,%p): stub\n", iface, rc); - return E_NOTIMPL; -} - static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl = { IMILBitmapImpl_QueryInterface, @@ -651,20 +593,26 @@ static const IMILBitmapSourceVtbl IMILBitmapImpl_Vtbl = IMILBitmapImpl_GetResolution, IMILBitmapImpl_CopyPalette, IMILBitmapImpl_CopyPixels, - IMILBitmapImpl_unknown1, - IMILBitmapImpl_Lock, - IMILBitmapImpl_Unlock, - IMILBitmapImpl_SetPalette, - IMILBitmapImpl_SetResolution, - IMILBitmapImpl_AddDirtyRect + IMILBitmapImpl_UnknownMethod1, }; static HRESULT WINAPI IMILUnknown1Impl_QueryInterface(IMILUnknown1 *iface, REFIID iid, void **ppv) { - FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv); - *ppv = NULL; - return E_NOINTERFACE; + BitmapImpl *This = impl_from_IMILUnknown1(iface); + + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid)) + { + IUnknown_AddRef(&This->IMILUnknown1_iface); + *ppv = iface; + return S_OK; + } + + return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv); } static ULONG WINAPI IMILUnknown1Impl_AddRef(IMILUnknown1 *iface) @@ -679,128 +627,66 @@ static ULONG WINAPI IMILUnknown1Impl_Release(IMILUnknown1 *iface) return IWICBitmap_Release(&This->IWICBitmap_iface); } -DECLSPEC_HIDDEN void WINAPI IMILUnknown1Impl_unknown1(IMILUnknown1 *iface, void *arg) -{ - FIXME("(%p,%p): stub\n", iface, arg); -} - -static HRESULT WINAPI IMILUnknown1Impl_unknown2(IMILUnknown1 *iface, void *arg1, void *arg2) -{ - FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); - return E_NOTIMPL; -} - -DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown3(IMILUnknown1 *iface, void *arg) -{ - FIXME("(%p,%p): stub\n", iface, arg); - return E_NOTIMPL; -} - -static HRESULT WINAPI IMILUnknown1Impl_unknown4(IMILUnknown1 *iface, void *arg) -{ - FIXME("(%p,%p): stub\n", iface, arg); - return E_NOTIMPL; -} - -static HRESULT WINAPI IMILUnknown1Impl_unknown5(IMILUnknown1 *iface, void *arg) -{ - FIXME("(%p,%p): stub\n", iface, arg); - return E_NOTIMPL; -} - -static HRESULT WINAPI IMILUnknown1Impl_unknown6(IMILUnknown1 *iface, DWORD64 arg) -{ - FIXME("(%p,%s): stub\n", iface, wine_dbgstr_longlong(arg)); - return E_NOTIMPL; -} - -static HRESULT WINAPI IMILUnknown1Impl_unknown7(IMILUnknown1 *iface, void *arg) -{ - FIXME("(%p,%p): stub\n", iface, arg); - return E_NOTIMPL; -} - -DECLSPEC_HIDDEN HRESULT WINAPI IMILUnknown1Impl_unknown8(IMILUnknown1 *iface) -{ - FIXME("(%p): stub\n", iface); - return E_NOTIMPL; -} - -DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown1, 8) -DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown3, 8) -DEFINE_THISCALL_WRAPPER(IMILUnknown1Impl_unknown8, 4) - static const IMILUnknown1Vtbl IMILUnknown1Impl_Vtbl = { IMILUnknown1Impl_QueryInterface, IMILUnknown1Impl_AddRef, IMILUnknown1Impl_Release, - THISCALL(IMILUnknown1Impl_unknown1), - IMILUnknown1Impl_unknown2, - THISCALL(IMILUnknown1Impl_unknown3), - IMILUnknown1Impl_unknown4, - IMILUnknown1Impl_unknown5, - IMILUnknown1Impl_unknown6, - IMILUnknown1Impl_unknown7, - THISCALL(IMILUnknown1Impl_unknown8) }; static HRESULT WINAPI IMILUnknown2Impl_QueryInterface(IMILUnknown2 *iface, REFIID iid, void **ppv) { - FIXME("(%p,%s,%p): stub\n", iface, debugstr_guid(iid), ppv); - *ppv = NULL; - return E_NOINTERFACE; + BitmapImpl *This = impl_from_IMILUnknown2(iface); + + TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); + + if (!ppv) return E_INVALIDARG; + + if (IsEqualIID(&IID_IUnknown, iid)) + { + IUnknown_AddRef(&This->IMILUnknown2_iface); + *ppv = iface; + return S_OK; + } + + return IWICBitmap_QueryInterface(&This->IWICBitmap_iface, iid, ppv); } static ULONG WINAPI IMILUnknown2Impl_AddRef(IMILUnknown2 *iface) { - FIXME("(%p): stub\n", iface); - return 0; + BitmapImpl *This = impl_from_IMILUnknown2(iface); + return IWICBitmap_AddRef(&This->IWICBitmap_iface); } static ULONG WINAPI IMILUnknown2Impl_Release(IMILUnknown2 *iface) { - FIXME("(%p): stub\n", iface); - return 0; -} - -static HRESULT WINAPI IMILUnknown2Impl_unknown1(IMILUnknown2 *iface, void *arg1, void **arg2) -{ - FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); - if (arg2) *arg2 = NULL; - return E_NOTIMPL; + BitmapImpl *This = impl_from_IMILUnknown2(iface); + return IWICBitmap_Release(&This->IWICBitmap_iface); } -static HRESULT WINAPI IMILUnknown2Impl_unknown2(IMILUnknown2 *iface, void *arg1, void *arg2) +static HRESULT WINAPI IMILUnknown2Impl_UnknownMethod1(IMILUnknown2 *iface, void *arg1, void *arg2) { FIXME("(%p,%p,%p): stub\n", iface, arg1, arg2); return E_NOTIMPL; } -static HRESULT WINAPI IMILUnknown2Impl_unknown3(IMILUnknown2 *iface, void *arg1) -{ - FIXME("(%p,%p): stub\n", iface, arg1); - return E_NOTIMPL; -} - static const IMILUnknown2Vtbl IMILUnknown2Impl_Vtbl = { IMILUnknown2Impl_QueryInterface, IMILUnknown2Impl_AddRef, IMILUnknown2Impl_Release, - IMILUnknown2Impl_unknown1, - IMILUnknown2Impl_unknown2, - IMILUnknown2Impl_unknown3 + IMILUnknown2Impl_UnknownMethod1, }; HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, - UINT stride, UINT datasize, BYTE *data, + UINT stride, UINT datasize, BYTE *bits, REFWICPixelFormatGUID pixelFormat, WICBitmapCreateCacheOption option, IWICBitmap **ppIBitmap) { HRESULT hr; BitmapImpl *This; + BYTE *data; UINT bpp; hr = get_pixelformat_bpp(pixelFormat, &bpp); @@ -813,20 +699,14 @@ HRESULT BitmapImpl_Create(UINT uiWidth, UINT uiHeight, if (stride < ((bpp*uiWidth)+7)/8) return E_INVALIDARG; This = HeapAlloc(GetProcessHeap(), 0, sizeof(BitmapImpl)); - if (!This) return E_OUTOFMEMORY; - - if (!data) + data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize); + if (!This || !data) { - data = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, datasize); - if (!data) - { - HeapFree(GetProcessHeap(), 0, This); - return E_OUTOFMEMORY; - } - This->is_section = FALSE; + HeapFree(GetProcessHeap(), 0, This); + HeapFree(GetProcessHeap(), 0, data); + return E_OUTOFMEMORY; } - else - This->is_section = TRUE; + if (bits) memcpy(data, bits, datasize); This->IWICBitmap_iface.lpVtbl = &BitmapImpl_Vtbl; This->IMILBitmapSource_iface.lpVtbl = &IMILBitmapImpl_Vtbl; diff --git a/dll/win32/windowscodecs/bmpdecode.c b/dll/win32/windowscodecs/bmpdecode.c index 395f71f1d8..5039694a76 100644 --- a/dll/win32/windowscodecs/bmpdecode.c +++ b/dll/win32/windowscodecs/bmpdecode.c @@ -256,7 +256,7 @@ static HRESULT WINAPI BmpFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, if (This->bih.bV5ClrUsed == 0) count = 1 << This->bih.bV5BitCount; else - count = min(This->bih.bV5ClrUsed, 1 << This->bih.bV5BitCount); + count = This->bih.bV5ClrUsed; tablesize = sizeof(WICColor) * count; wiccolors = HeapAlloc(GetProcessHeap(), 0, tablesize); diff --git a/dll/win32/windowscodecs/bmpencode.c b/dll/win32/windowscodecs/bmpencode.c index 5bc043a4db..e339324015 100644 --- a/dll/win32/windowscodecs/bmpencode.c +++ b/dll/win32/windowscodecs/bmpencode.c @@ -1,6 +1,5 @@ /* * Copyright 2009 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 @@ -24,7 +23,6 @@ struct bmp_pixelformat { const WICPixelFormatGUID *guid; UINT bpp; - UINT colors; /* palette size */ DWORD compression; DWORD redmask; DWORD greenmask; @@ -33,18 +31,13 @@ struct bmp_pixelformat { }; static const struct bmp_pixelformat formats[] = { - {&GUID_WICPixelFormat24bppBGR, 24, 0, BI_RGB}, - {&GUID_WICPixelFormatBlackWhite, 1, 2, BI_RGB}, - {&GUID_WICPixelFormat1bppIndexed, 1, 2, BI_RGB}, - {&GUID_WICPixelFormat2bppIndexed, 2, 4, BI_RGB}, - {&GUID_WICPixelFormat4bppIndexed, 4, 16, BI_RGB}, - {&GUID_WICPixelFormat8bppIndexed, 8, 256, BI_RGB}, - {&GUID_WICPixelFormat16bppBGR555, 16, 0, BI_RGB}, - {&GUID_WICPixelFormat16bppBGR565, 16, 0, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0}, - {&GUID_WICPixelFormat32bppBGR, 32, 0, BI_RGB}, + {&GUID_WICPixelFormat24bppBGR, 24, BI_RGB}, + {&GUID_WICPixelFormat16bppBGR555, 16, BI_RGB}, + {&GUID_WICPixelFormat16bppBGR565, 16, BI_BITFIELDS, 0xf800, 0x7e0, 0x1f, 0}, + {&GUID_WICPixelFormat32bppBGR, 32, BI_RGB}, #if 0 /* Windows doesn't seem to support this one. */ - {&GUID_WICPixelFormat32bppBGRA, 32, 0, BI_BITFIELDS, 0xff0000, 0xff00, 0xff, 0xff000000}, + {&GUID_WICPixelFormat32bppBGRA, 32, BI_BITFIELDS, 0xff0000, 0xff00, 0xff, 0xff000000}, #endif {NULL} }; @@ -172,13 +165,11 @@ static HRESULT WINAPI BmpFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface for (i=0; formats[i].guid; i++) { - if (IsEqualGUID(formats[i].guid, pPixelFormat)) + if (memcmp(formats[i].guid, pPixelFormat, sizeof(GUID)) == 0) break; } if (!formats[i].guid) i = 0; - else if (IsEqualGUID(pPixelFormat, &GUID_WICPixelFormatBlackWhite)) - i = 2; /* GUID_WICPixelFormat1bppIndexed */ This->format = &formats[i]; memcpy(pPixelFormat, This->format->guid, sizeof(GUID)); @@ -197,7 +188,6 @@ static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface, IWICPalette *palette) { BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; TRACE("(%p,%p)\n", iface, palette); @@ -206,14 +196,7 @@ static HRESULT WINAPI BmpFrameEncode_SetPalette(IWICBitmapFrameEncode *iface, if (!This->initialized) return WINCODEC_ERR_NOTINITIALIZED; - hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors); - if (hr == S_OK) - { - UINT i; - for (i = 0; i < This->colors; i++) - This->palette[i] |= 0xff000000; /* BMP palette has no alpha */ - } - return hr; + return IWICPalette_GetColors(palette, 256, This->palette, &This->colors); } static HRESULT WINAPI BmpFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface, @@ -295,11 +278,10 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) BmpFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); BITMAPFILEHEADER bfh; BITMAPV5HEADER bih; - UINT info_size, i; + UINT info_size; LARGE_INTEGER pos; ULONG byteswritten; HRESULT hr; - const BYTE *bits; TRACE("(%p)\n", iface); @@ -312,15 +294,15 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) bih.bV5Size = info_size = sizeof(BITMAPINFOHEADER); bih.bV5Width = This->width; - bih.bV5Height = This->height; /* bottom-top bitmap */ + bih.bV5Height = -This->height; /* top-down bitmap */ bih.bV5Planes = 1; bih.bV5BitCount = This->format->bpp; bih.bV5Compression = This->format->compression; bih.bV5SizeImage = This->stride*This->height; bih.bV5XPelsPerMeter = (This->xres+0.0127) / 0.0254; bih.bV5YPelsPerMeter = (This->yres+0.0127) / 0.0254; - bih.bV5ClrUsed = (This->format->bpp <= 8) ? This->colors : 0; - bih.bV5ClrImportant = bih.bV5ClrUsed; + bih.bV5ClrUsed = 0; + bih.bV5ClrImportant = 0; if (This->format->compression == BI_BITFIELDS) { @@ -337,7 +319,6 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) bfh.bfSize = sizeof(BITMAPFILEHEADER) + info_size + bih.bV5SizeImage; bfh.bfOffBits = sizeof(BITMAPFILEHEADER) + info_size; - bfh.bfOffBits += bih.bV5ClrUsed * sizeof(WICColor); pos.QuadPart = 0; hr = IStream_Seek(This->stream, pos, STREAM_SEEK_SET, NULL); @@ -351,23 +332,9 @@ static HRESULT WINAPI BmpFrameEncode_Commit(IWICBitmapFrameEncode *iface) if (FAILED(hr)) return hr; if (byteswritten != info_size) return E_FAIL; - /* write the palette */ - if (This->format->colors) - { - hr = IStream_Write(This->stream, This->palette, This->colors * sizeof(WICColor), &byteswritten); - if (FAILED(hr)) return hr; - if (byteswritten != This->colors * sizeof(WICColor)) return E_FAIL; - } - - /* write the image bits as a bottom-top array */ - bits = This->bits + bih.bV5SizeImage; - for (i = 0; i < This->height; i++) - { - bits -= This->stride; - hr = IStream_Write(This->stream, bits, This->stride, &byteswritten); - if (FAILED(hr)) return hr; - if (byteswritten != This->stride) return E_FAIL; - } + hr = IStream_Write(This->stream, This->bits, bih.bV5SizeImage, &byteswritten); + if (FAILED(hr)) return hr; + if (byteswritten != bih.bV5SizeImage) return E_FAIL; This->committed = TRUE; @@ -480,22 +447,11 @@ static HRESULT WINAPI BmpEncoder_GetContainerFormat(IWICBitmapEncoder *iface, return S_OK; } -static HRESULT WINAPI BmpEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info) +static HRESULT WINAPI BmpEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, + IWICBitmapEncoderInfo **ppIEncoderInfo) { - IWICComponentInfo *comp_info; - HRESULT hr; - - TRACE("%p,%p\n", iface, info); - - if (!info) return E_INVALIDARG; - - hr = CreateComponentInfo(&CLSID_WICBmpEncoder, &comp_info); - if (hr == S_OK) - { - hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info); - IWICComponentInfo_Release(comp_info); - } - return hr; + FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo); + return E_NOTIMPL; } static HRESULT WINAPI BmpEncoder_SetColorContexts(IWICBitmapEncoder *iface, diff --git a/dll/win32/windowscodecs/clsfactory.c b/dll/win32/windowscodecs/clsfactory.c index 079ae762b8..2116ff9e8b 100644 --- a/dll/win32/windowscodecs/clsfactory.c +++ b/dll/win32/windowscodecs/clsfactory.c @@ -32,7 +32,6 @@ static const classinfo wic_classes[] = { {&CLSID_WICPngEncoder, PngEncoder_CreateInstance}, {&CLSID_WICBmpEncoder, BmpEncoder_CreateInstance}, {&CLSID_WICGifDecoder, GifDecoder_CreateInstance}, - {&CLSID_WICGifEncoder, GifEncoder_CreateInstance}, {&CLSID_WICIcoDecoder, IcoDecoder_CreateInstance}, {&CLSID_WICJpegDecoder, JpegDecoder_CreateInstance}, {&CLSID_WICJpegEncoder, JpegEncoder_CreateInstance}, diff --git a/dll/win32/windowscodecs/converter.c b/dll/win32/windowscodecs/converter.c index 3fca5b38f6..d6086b087a 100644 --- a/dll/win32/windowscodecs/converter.c +++ b/dll/win32/windowscodecs/converter.c @@ -40,11 +40,8 @@ enum pixelformat { format_24bppRGB, format_32bppGrayFloat, format_32bppBGR, - format_32bppRGB, format_32bppBGRA, - format_32bppRGBA, format_32bppPBGRA, - format_32bppPRGBA, format_48bppRGB, format_64bppRGBA, format_32bppCMYK, @@ -66,7 +63,7 @@ typedef struct FormatConverter { const struct pixelformatinfo *dst_format, *src_format; WICBitmapDitherType dither; double alpha_threshold; - IWICPalette *palette; + WICBitmapPaletteType palette_type; CRITICAL_SECTION lock; /* must be held when initialized */ } FormatConverter; @@ -850,27 +847,6 @@ static HRESULT copypixels_to_32bppBGRA(struct FormatConverter *This, const WICRe } } -static HRESULT copypixels_to_32bppRGBA(struct FormatConverter *This, const WICRect *prc, - UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) -{ - HRESULT hr; - - switch (source_format) - { - case format_32bppRGB: - case format_32bppRGBA: - case format_32bppPRGBA: - if (prc) - return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); - return S_OK; - default: - hr = copypixels_to_32bppBGRA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); - if (SUCCEEDED(hr) && prc) - reverse_bgr8(4, pbBuffer, prc->Width, prc->Height, cbStride); - return hr; - } -} - static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) { @@ -887,22 +863,6 @@ static HRESULT copypixels_to_32bppBGR(struct FormatConverter *This, const WICRec } } -static HRESULT copypixels_to_32bppRGB(struct FormatConverter *This, const WICRect *prc, - UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) -{ - switch (source_format) - { - case format_32bppRGB: - case format_32bppRGBA: - case format_32bppPRGBA: - if (prc) - return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); - return S_OK; - default: - return copypixels_to_32bppRGBA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); - } -} - static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) { @@ -936,39 +896,6 @@ static HRESULT copypixels_to_32bppPBGRA(struct FormatConverter *This, const WICR } } -static HRESULT copypixels_to_32bppPRGBA(struct FormatConverter *This, const WICRect *prc, - UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) -{ - HRESULT hr; - - switch (source_format) - { - case format_32bppPRGBA: - if (prc) - return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); - return S_OK; - default: - hr = copypixels_to_32bppRGBA(This, prc, cbStride, cbBufferSize, pbBuffer, source_format); - if (SUCCEEDED(hr) && prc) - { - INT x, y; - - for (y=0; y<prc->Height; y++) - for (x=0; x<prc->Width; x++) - { - BYTE alpha = pbBuffer[cbStride*y+4*x+3]; - if (alpha != 255) - { - pbBuffer[cbStride*y+4*x] = pbBuffer[cbStride*y+4*x] * alpha / 255; - pbBuffer[cbStride*y+4*x+1] = pbBuffer[cbStride*y+4*x+1] * alpha / 255; - pbBuffer[cbStride*y+4*x+2] = pbBuffer[cbStride*y+4*x+2] * alpha / 255; - } - } - } - return hr; - } -} - static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) { @@ -1074,48 +1001,6 @@ static HRESULT copypixels_to_24bppBGR(struct FormatConverter *This, const WICRec } return S_OK; - case format_32bppCMYK: - if (prc) - { - BYTE *srcdata; - UINT srcstride, srcdatasize; - - srcstride = 4 * prc->Width; - srcdatasize = srcstride * prc->Height; - - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); - if (!srcdata) return E_OUTOFMEMORY; - - hr = IWICBitmapSource_CopyPixels(This->source, prc, srcstride, srcdatasize, srcdata); - if (SUCCEEDED(hr)) - { - INT x, y; - BYTE *src = srcdata, *dst = pbBuffer; - - for (y = 0; y < prc->Height; y++) - { - BYTE *cmyk = src; - BYTE *bgr = dst; - - for (x = 0; x < prc->Width; x++) - { - BYTE c = cmyk[0], m = cmyk[1], y = cmyk[2], k = cmyk[3]; - bgr[0] = (255 - y) * (255 - k) / 255; /* B */ - bgr[1] = (255 - m) * (255 - k) / 255; /* G */ - bgr[2] = (255 - c) * (255 - k) / 255; /* R */ - cmyk += 4; - bgr += 3; - } - src += srcstride; - dst += cbStride; - } - } - - HeapFree(GetProcessHeap(), 0, srcdata); - return hr; - } - return S_OK; - default: FIXME("Unimplemented conversion path!\n"); return WINCODEC_ERR_UNSUPPORTEDOPERATION; @@ -1323,95 +1208,11 @@ static HRESULT copypixels_to_8bppGray(struct FormatConverter *This, const WICRec return hr; } -static UINT rgb_to_palette_index(BYTE r, BYTE g, BYTE b, WICColor *colors, UINT count) -{ - UINT best_diff, best_index, i; - - best_diff = ~0; - best_index = 0; - - for (i = 0; i < count; i++) - { - BYTE pal_r, pal_g, pal_b; - DWORD diff_r, diff_g, diff_b, diff; - - pal_r = colors[i] >> 16; - pal_g = colors[i] >> 8; - pal_b = colors[i]; - - diff_r = r - pal_r; - diff_g = g - pal_g; - diff_b = b - pal_b; - - diff = diff_r * diff_r + diff_g * diff_g + diff_b * diff_b; - if (diff == 0) return i; - - if (diff < best_diff) - { - best_diff = diff; - best_index = i; - } - } - - return best_index; -} - -static HRESULT copypixels_to_8bppIndexed(struct FormatConverter *This, const WICRect *prc, - UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer, enum pixelformat source_format) -{ - HRESULT hr; - BYTE *srcdata; - WICColor colors[256]; - UINT srcstride, srcdatasize, count; - - if (source_format == format_8bppIndexed) - { - if (prc) - return IWICBitmapSource_CopyPixels(This->source, prc, cbStride, cbBufferSize, pbBuffer); - - return S_OK; - } - - if (!This->palette) return WINCODEC_ERR_WRONGSTATE; - - hr = IWICPalette_GetColors(This->palette, 256, colors, &count); - if (hr != S_OK) return hr; - - srcstride = 3 * prc->Width; - srcdatasize = srcstride * prc->Height; - - srcdata = HeapAlloc(GetProcessHeap(), 0, srcdatasize); - if (!srcdata) return E_OUTOFMEMORY; - - hr = copypixels_to_24bppBGR(This, prc, srcstride, srcdatasize, srcdata, source_format); - if (SUCCEEDED(hr) && prc) - { - INT x, y; - BYTE *src = srcdata, *dst = pbBuffer; - - for (y = 0; y < prc->Height; y++) - { - BYTE *bgr = src; - - for (x = 0; x < prc->Width; x++) - { - dst[x] = rgb_to_palette_index(bgr[2], bgr[1], bgr[0], colors, count); - bgr += 3; - } - src += srcstride; - dst += cbStride; - } - } - - HeapFree(GetProcessHeap(), 0, srcdata); - return hr; -} - static const struct pixelformatinfo supported_formats[] = { {format_1bppIndexed, &GUID_WICPixelFormat1bppIndexed, NULL}, {format_2bppIndexed, &GUID_WICPixelFormat2bppIndexed, NULL}, {format_4bppIndexed, &GUID_WICPixelFormat4bppIndexed, NULL}, - {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, copypixels_to_8bppIndexed}, + {format_8bppIndexed, &GUID_WICPixelFormat8bppIndexed, NULL}, {format_BlackWhite, &GUID_WICPixelFormatBlackWhite, NULL}, {format_2bppGray, &GUID_WICPixelFormat2bppGray, NULL}, {format_4bppGray, &GUID_WICPixelFormat4bppGray, NULL}, @@ -1424,11 +1225,8 @@ static const struct pixelformatinfo supported_formats[] = { {format_24bppRGB, &GUID_WICPixelFormat24bppRGB, copypixels_to_24bppRGB}, {format_32bppGrayFloat, &GUID_WICPixelFormat32bppGrayFloat, copypixels_to_32bppGrayFloat}, {format_32bppBGR, &GUID_WICPixelFormat32bppBGR, copypixels_to_32bppBGR}, - {format_32bppRGB, &GUID_WICPixelFormat32bppRGB, copypixels_to_32bppRGB}, {format_32bppBGRA, &GUID_WICPixelFormat32bppBGRA, copypixels_to_32bppBGRA}, - {format_32bppRGBA, &GUID_WICPixelFormat32bppRGBA, copypixels_to_32bppRGBA}, {format_32bppPBGRA, &GUID_WICPixelFormat32bppPBGRA, copypixels_to_32bppPBGRA}, - {format_32bppPRGBA, &GUID_WICPixelFormat32bppPRGBA, copypixels_to_32bppPRGBA}, {format_48bppRGB, &GUID_WICPixelFormat48bppRGB, NULL}, {format_64bppRGBA, &GUID_WICPixelFormat64bppRGBA, NULL}, {format_32bppCMYK, &GUID_WICPixelFormat32bppCMYK, NULL}, @@ -1491,7 +1289,6 @@ static ULONG WINAPI FormatConverter_Release(IWICFormatConverter *iface) This->lock.DebugInfo->Spare[0] = 0; DeleteCriticalSection(&This->lock); if (This->source) IWICBitmapSource_Release(This->source); - if (This->palette) IWICPalette_Release(This->palette); HeapFree(GetProcessHeap(), 0, This); } @@ -1540,27 +1337,10 @@ static HRESULT WINAPI FormatConverter_GetResolution(IWICFormatConverter *iface, } static HRESULT WINAPI FormatConverter_CopyPalette(IWICFormatConverter *iface, - IWICPalette *palette) + IWICPalette *pIPalette) { - FormatConverter *This = impl_from_IWICFormatConverter(iface); - - TRACE("(%p,%p)\n", iface, palette); - - if (!palette) return E_INVALIDARG; - if (!This->source) return WINCODEC_ERR_WRONGSTATE; - - if (!This->palette) - { - HRESULT hr; - UINT bpp; - - hr = get_pixelformat_bpp(This->dst_format->guid, &bpp); - if (hr != S_OK) return hr; - if (bpp <= 8) return WINCODEC_ERR_WRONGSTATE; - return IWICBitmapSource_CopyPalette(This->source, palette); - } - - return IWICPalette_InitializeFromPalette(palette, This->palette); + FIXME("(%p,%p): stub\n", iface, pIPalette); + return E_NOTIMPL; } static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface, @@ -1589,59 +1369,23 @@ static HRESULT WINAPI FormatConverter_CopyPixels(IWICFormatConverter *iface, pbBuffer, This->src_format->format); } else - return WINCODEC_ERR_WRONGSTATE; + return WINCODEC_ERR_NOTINITIALIZED; } static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, - IWICBitmapSource *source, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither, - IWICPalette *palette, double alpha_threshold, WICBitmapPaletteType palette_type) + IWICBitmapSource *pISource, REFWICPixelFormatGUID dstFormat, WICBitmapDitherType dither, + IWICPalette *pIPalette, double alphaThresholdPercent, WICBitmapPaletteType paletteTranslate) { FormatConverter *This = impl_from_IWICFormatConverter(iface); const struct pixelformatinfo *srcinfo, *dstinfo; + static INT fixme=0; GUID srcFormat; - HRESULT res; - - TRACE("(%p,%p,%s,%u,%p,%0.3f,%u)\n", iface, source, debugstr_guid(dstFormat), - dither, palette, alpha_threshold, palette_type); - - if (!palette) - { - UINT bpp; - res = get_pixelformat_bpp(dstFormat, &bpp); - if (res != S_OK) return res; - - res = PaletteImpl_Create(&palette); - if (res != S_OK) return res; - - switch (palette_type) - { - case WICBitmapPaletteTypeCustom: - IWICPalette_Release(palette); - palette = NULL; - if (bpp <= 8) return E_INVALIDARG; - break; - - case WICBitmapPaletteTypeMedianCut: - { - if (bpp <= 8) - res = IWICPalette_InitializeFromBitmap(palette, source, 1 << bpp, FALSE); - break; - } + HRESULT res=S_OK; - default: - if (bpp <= 8) - res = IWICPalette_InitializePredefined(palette, palette_type, FALSE); - break; - } + TRACE("(%p,%p,%s,%u,%p,%0.1f,%u)\n", iface, pISource, debugstr_guid(dstFormat), + dither, pIPalette, alphaThresholdPercent, paletteTranslate); - if (res != S_OK) - { - IWICPalette_Release(palette); - return res; - } - } - else - IWICPalette_AddRef(palette); + if (pIPalette && !fixme++) FIXME("ignoring palette\n"); EnterCriticalSection(&This->lock); @@ -1651,7 +1395,7 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, goto end; } - res = IWICBitmapSource_GetPixelFormat(source, &srcFormat); + res = IWICBitmapSource_GetPixelFormat(pISource, &srcFormat); if (FAILED(res)) goto end; srcinfo = get_formatinfo(&srcFormat); @@ -1672,13 +1416,13 @@ static HRESULT WINAPI FormatConverter_Initialize(IWICFormatConverter *iface, if (dstinfo->copy_function) { - IWICBitmapSource_AddRef(source); + IWICBitmapSource_AddRef(pISource); This->src_format = srcinfo; This->dst_format = dstinfo; This->dither = dither; - This->alpha_threshold = alpha_threshold; - This->palette = palette; - This->source = source; + This->alpha_threshold = alphaThresholdPercent; + This->palette_type = paletteTranslate; + This->source = pISource; } else { @@ -1690,9 +1434,6 @@ end: LeaveCriticalSection(&This->lock); - if (res != S_OK && palette) - IWICPalette_Release(palette); - return res; } @@ -1760,7 +1501,6 @@ HRESULT FormatConverter_CreateInstance(REFIID iid, void** ppv) This->IWICFormatConverter_iface.lpVtbl = &FormatConverter_Vtbl; This->ref = 1; This->source = NULL; - This->palette = NULL; InitializeCriticalSection(&This->lock); This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": FormatConverter.lock"); diff --git a/dll/win32/windowscodecs/gifformat.c b/dll/win32/windowscodecs/gifformat.c index 3a023d4963..3bc3bac409 100644 --- a/dll/win32/windowscodecs/gifformat.c +++ b/dll/win32/windowscodecs/gifformat.c @@ -1,6 +1,6 @@ /* * Copyright 2009 Vincent Povirk for CodeWeavers - * Copyright 2012,2016 Dmitry Timoshkov + * Copyright 2012 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -23,40 +23,6 @@ #include "ungif.h" -#include "pshpack1.h" - -struct logical_screen_descriptor -{ - char signature[6]; - USHORT width; - USHORT height; - BYTE packed; - /* global_color_table_flag : 1; - * color_resolution : 3; - * sort_flag : 1; - * global_color_table_size : 3; - */ - BYTE background_color_index; - BYTE pixel_aspect_ratio; -}; - -struct image_descriptor -{ - USHORT left; - USHORT top; - USHORT width; - USHORT height; - BYTE packed; - /* local_color_table_flag : 1; - * interlace_flag : 1; - * sort_flag : 1; - * reserved : 2; - * local_color_table_size : 3; - */ -}; - -#include "poppack.h" - static LPWSTR strdupAtoW(const char *src) { int len = MultiByteToWideChar(CP_ACP, 0, src, -1, NULL, 0); @@ -68,7 +34,22 @@ static LPWSTR strdupAtoW(const char *src) static HRESULT load_LSD_metadata(IStream *stream, const GUID *vendor, DWORD options, MetadataItem **items, DWORD *count) { - struct logical_screen_descriptor lsd_data; +#include "pshpack1.h" + struct logical_screen_descriptor + { + char signature[6]; + USHORT width; + USHORT height; + BYTE packed; + /* global_color_table_flag : 1; + * color_resolution : 3; + * sort_flag : 1; + * global_color_table_size : 3; + */ + BYTE background_color_index; + BYTE pixel_aspect_ratio; + } lsd_data; +#include "poppack.h" HRESULT hr; ULONG bytesread, i; MetadataItem *result; @@ -153,6 +134,23 @@ HRESULT LSDReader_CreateInstance(REFIID iid, void **ppv) return MetadataReader_Create(&LSDReader_Vtbl, iid, ppv); } +#include "pshpack1.h" +struct image_descriptor +{ + USHORT left; + USHORT top; + USHORT width; + USHORT height; + BYTE packed; + /* local_color_table_flag : 1; + * interlace_flag : 1; + * sort_flag : 1; + * reserved : 2; + * local_color_table_size : 3; + */ +}; +#include "poppack.h" + static HRESULT load_IMD_metadata(IStream *stream, const GUID *vendor, DWORD options, MetadataItem **items, DWORD *count) { @@ -1185,9 +1183,6 @@ static HRESULT WINAPI GifDecoder_CopyPalette(IWICBitmapDecoder *iface, IWICPalet TRACE("(%p,%p)\n", iface, palette); - if (!This->gif) - return WINCODEC_ERR_WRONGSTATE; - cm = This->gif->SColorMap; if (cm) { @@ -1452,945 +1447,3 @@ HRESULT GifDecoder_CreateInstance(REFIID iid, void** ppv) return ret; } - -typedef struct GifEncoder -{ - IWICBitmapEncoder IWICBitmapEncoder_iface; - LONG ref; - IStream *stream; - CRITICAL_SECTION lock; - BOOL initialized, info_written, committed; - UINT n_frames; - WICColor palette[256]; - UINT colors; -} GifEncoder; - -static inline GifEncoder *impl_from_IWICBitmapEncoder(IWICBitmapEncoder *iface) -{ - return CONTAINING_RECORD(iface, GifEncoder, IWICBitmapEncoder_iface); -} - -typedef struct GifFrameEncode -{ - IWICBitmapFrameEncode IWICBitmapFrameEncode_iface; - LONG ref; - GifEncoder *encoder; - BOOL initialized, interlace, committed; - UINT width, height, lines; - double xres, yres; - WICColor palette[256]; - UINT colors; - BYTE *image_data; -} GifFrameEncode; - -static inline GifFrameEncode *impl_from_IWICBitmapFrameEncode(IWICBitmapFrameEncode *iface) -{ - return CONTAINING_RECORD(iface, GifFrameEncode, IWICBitmapFrameEncode_iface); -} - -static HRESULT WINAPI GifFrameEncode_QueryInterface(IWICBitmapFrameEncode *iface, REFIID iid, void **ppv) -{ - TRACE("%p,%s,%p\n", iface, debugstr_guid(iid), ppv); - - if (!ppv) return E_INVALIDARG; - - if (IsEqualIID(&IID_IUnknown, iid) || - IsEqualIID(&IID_IWICBitmapFrameEncode, iid)) - { - IWICBitmapFrameEncode_AddRef(iface); - *ppv = iface; - return S_OK; - } - - *ppv = NULL; - return E_NOINTERFACE; -} - -static ULONG WINAPI GifFrameEncode_AddRef(IWICBitmapFrameEncode *iface) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - ULONG ref = InterlockedIncrement(&This->ref); - - TRACE("%p -> %u\n", iface, ref); - return ref; -} - -static ULONG WINAPI GifFrameEncode_Release(IWICBitmapFrameEncode *iface) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE("%p -> %u\n", iface, ref); - - if (!ref) - { - IWICBitmapEncoder_Release(&This->encoder->IWICBitmapEncoder_iface); - HeapFree(GetProcessHeap(), 0, This->image_data); - HeapFree(GetProcessHeap(), 0, This); - } - - return ref; -} - -static HRESULT WINAPI GifFrameEncode_Initialize(IWICBitmapFrameEncode *iface, IPropertyBag2 *options) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; - - TRACE("%p,%p\n", iface, options); - - EnterCriticalSection(&This->encoder->lock); - - if (!This->initialized) - { - This->initialized = TRUE; - hr = S_OK; - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->encoder->lock); - - return hr; -} - -static HRESULT WINAPI GifFrameEncode_SetSize(IWICBitmapFrameEncode *iface, UINT width, UINT height) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; - - TRACE("%p,%u,%u\n", iface, width, height); - - if (!width || !height) return E_INVALIDARG; - - EnterCriticalSection(&This->encoder->lock); - - if (This->initialized) - { - HeapFree(GetProcessHeap(), 0, This->image_data); - - This->image_data = HeapAlloc(GetProcessHeap(), 0, width * height); - if (This->image_data) - { - This->width = width; - This->height = height; - hr = S_OK; - } - else - hr = E_OUTOFMEMORY; - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->encoder->lock); - - return hr; -} - -static HRESULT WINAPI GifFrameEncode_SetResolution(IWICBitmapFrameEncode *iface, double xres, double yres) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; - - TRACE("%p,%f,%f\n", iface, xres, yres); - - EnterCriticalSection(&This->encoder->lock); - - if (This->initialized) - { - This->xres = xres; - This->yres = yres; - hr = S_OK; - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->encoder->lock); - - return hr; -} - -static HRESULT WINAPI GifFrameEncode_SetPixelFormat(IWICBitmapFrameEncode *iface, WICPixelFormatGUID *format) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; - - TRACE("%p,%s\n", iface, debugstr_guid(format)); - - if (!format) return E_INVALIDARG; - - EnterCriticalSection(&This->encoder->lock); - - if (This->initialized) - { - *format = GUID_WICPixelFormat8bppIndexed; - hr = S_OK; - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->encoder->lock); - - return hr; -} - -static HRESULT WINAPI GifFrameEncode_SetColorContexts(IWICBitmapFrameEncode *iface, UINT count, IWICColorContext **context) -{ - FIXME("%p,%u,%p: stub\n", iface, count, context); - return E_NOTIMPL; -} - -static HRESULT WINAPI GifFrameEncode_SetPalette(IWICBitmapFrameEncode *iface, IWICPalette *palette) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; - - TRACE("%p,%p\n", iface, palette); - - if (!palette) return E_INVALIDARG; - - EnterCriticalSection(&This->encoder->lock); - - if (This->initialized) - hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors); - else - hr = WINCODEC_ERR_NOTINITIALIZED; - - LeaveCriticalSection(&This->encoder->lock); - return hr; -} - -static HRESULT WINAPI GifFrameEncode_SetThumbnail(IWICBitmapFrameEncode *iface, IWICBitmapSource *thumbnail) -{ - FIXME("%p,%p: stub\n", iface, thumbnail); - return E_NOTIMPL; -} - -static HRESULT WINAPI GifFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, UINT lines, UINT stride, UINT size, BYTE *pixels) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; - - TRACE("%p,%u,%u,%u,%p\n", iface, lines, stride, size, pixels); - - if (!pixels) return E_INVALIDARG; - - EnterCriticalSection(&This->encoder->lock); - - if (This->initialized && This->image_data) - { - if (This->lines + lines <= This->height) - { - UINT i; - BYTE *src, *dst; - - src = pixels; - dst = This->image_data + This->lines * This->width; - - for (i = 0; i < lines; i++) - { - memcpy(dst, src, This->width); - src += stride; - dst += This->width; - } - - This->lines += lines; - hr = S_OK; - } - else - hr = E_INVALIDARG; - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->encoder->lock); - return hr; -} - -static HRESULT WINAPI GifFrameEncode_WriteSource(IWICBitmapFrameEncode *iface, IWICBitmapSource *source, WICRect *rc) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; - - TRACE("%p,%p,%p\n", iface, source, rc); - - if (!source) return E_INVALIDARG; - - EnterCriticalSection(&This->encoder->lock); - - if (This->initialized) - { - const GUID *format = &GUID_WICPixelFormat8bppIndexed; - - hr = configure_write_source(iface, source, rc, format, - This->width, This->height, This->xres, This->yres); - if (hr == S_OK) - hr = write_source(iface, source, rc, format, 8, This->width, This->height); - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->encoder->lock); - return hr; -} - -#define LZW_DICT_SIZE (1 << 12) - -struct lzw_dict -{ - short prefix[LZW_DICT_SIZE]; - unsigned char suffix[LZW_DICT_SIZE]; -}; - -struct lzw_state -{ - struct lzw_dict dict; - short init_code_bits, code_bits, next_code, clear_code, eof_code; - unsigned bits_buf; - int bits_count; - int (*user_write_data)(void *user_ptr, void *data, int length); - void *user_ptr; -}; - -struct input_stream -{ - unsigned len; - const BYTE *in; -}; - -struct output_stream -{ - struct - { - unsigned char len; - char data[255]; - } gif_block; - IStream *out; -}; - -static int lzw_output_code(struct lzw_state *state, short code) -{ - state->bits_buf |= code << state->bits_count; - state->bits_count += state->code_bits; - - while (state->bits_count >= 8) - { - unsigned char byte = (unsigned char)state->bits_buf; - if (state->user_write_data(state->user_ptr, &byte, 1) != 1) - return 0; - state->bits_buf >>= 8; - state->bits_count -= 8; - } - - return 1; -} - -static inline int lzw_output_clear_code(struct lzw_state *state) -{ - return lzw_output_code(state, state->clear_code); -} - -static inline int lzw_output_eof_code(struct lzw_state *state) -{ - return lzw_output_code(state, state->eof_code); -} - -static int lzw_flush_bits(struct lzw_state *state) -{ - unsigned char byte; - - while (state->bits_count >= 8) - { - byte = (unsigned char)state->bits_buf; - if (state->user_write_data(state->user_ptr, &byte, 1) != 1) - return 0; - state->bits_buf >>= 8; - state->bits_count -= 8; - } - - if (state->bits_count) - { - static const char mask[8] = { 0x00,0x01,0x03,0x07,0x0f,0x1f,0x3f,0x7f }; - - byte = (unsigned char)state->bits_buf & mask[state->bits_count]; - if (state->user_write_data(state->user_ptr, &byte, 1) != 1) - return 0; - } - - state->bits_buf = 0; - state->bits_count = 0; - - return 1; -} - -static void lzw_dict_reset(struct lzw_state *state) -{ - int i; - - state->code_bits = state->init_code_bits + 1; - state->next_code = (1 << state->init_code_bits) + 2; - - for(i = 0; i < LZW_DICT_SIZE; i++) - { - state->dict.prefix[i] = 1 << 12; /* impossible LZW code value */ - state->dict.suffix[i] = 0; - } -} - -static void lzw_state_init(struct lzw_state *state, short init_code_bits, void *user_write_data, void *user_ptr) -{ - state->init_code_bits = init_code_bits; - state->clear_code = 1 << init_code_bits; - state->eof_code = state->clear_code + 1; - state->bits_buf = 0; - state->bits_count = 0; - state->user_write_data = user_write_data; - state->user_ptr = user_ptr; - - lzw_dict_reset(state); -} - -static int lzw_dict_add(struct lzw_state *state, short prefix, unsigned char suffix) -{ - if (state->next_code < LZW_DICT_SIZE) - { - state->dict.prefix[state->next_code] = prefix; - state->dict.suffix[state->next_code] = suffix; - - if ((state->next_code & (state->next_code - 1)) == 0) - state->code_bits++; - - state->next_code++; - return state->next_code; - } - - return -1; -} - -static short lzw_dict_lookup(const struct lzw_state *state, short prefix, unsigned char suffix) -{ - short i; - - for (i = 0; i < state->next_code; i++) - { - if (state->dict.prefix[i] == prefix && state->dict.suffix[i] == suffix) - return i; - } - - return -1; -} - -static inline int write_byte(struct output_stream *out, char byte) -{ - if (out->gif_block.len == 255) - { - if (IStream_Write(out->out, &out->gif_block, sizeof(out->gif_block), NULL) != S_OK) - return 0; - - out->gif_block.len = 0; - } - - out->gif_block.data[out->gif_block.len++] = byte; - - return 1; -} - -static int write_data(void *user_ptr, void *user_data, int length) -{ - unsigned char *data = user_data; - struct output_stream *out = user_ptr; - int len = length; - - while (len-- > 0) - { - if (!write_byte(out, *data++)) return 0; - } - - return length; -} - -static int flush_output_data(void *user_ptr) -{ - struct output_stream *out = user_ptr; - - if (out->gif_block.len) - { - if (IStream_Write(out->out, &out->gif_block, out->gif_block.len + sizeof(out->gif_block.len), NULL) != S_OK) - return 0; - } - - /* write GIF block terminator */ - out->gif_block.len = 0; - return IStream_Write(out->out, &out->gif_block, sizeof(out->gif_block.len), NULL) == S_OK; -} - -static inline int read_byte(struct input_stream *in, unsigned char *byte) -{ - if (in->len) - { - in->len--; - *byte = *in->in++; - return 1; - } - - return 0; -} - -static HRESULT gif_compress(IStream *out_stream, const BYTE *in_data, ULONG in_size) -{ - struct input_stream in; - struct output_stream out; - struct lzw_state state; - short init_code_bits, prefix, code; - unsigned char suffix; - - in.in = in_data; - in.len = in_size; - - out.gif_block.len = 0; - out.out = out_stream; - - init_code_bits = suffix = 8; - if (IStream_Write(out.out, &suffix, sizeof(suffix), NULL) != S_OK) - return E_FAIL; - - lzw_state_init(&state, init_code_bits, write_data, &out); - - if (!lzw_output_clear_code(&state)) - return E_FAIL; - - if (read_byte(&in, &suffix)) - { - prefix = suffix; - - while (read_byte(&in, &suffix)) - { - code = lzw_dict_lookup(&state, prefix, suffix); - if (code == -1) - { - if (!lzw_output_code(&state, prefix)) - return E_FAIL; - - if (lzw_dict_add(&state, prefix, suffix) == -1) - { - if (!lzw_output_clear_code(&state)) - return E_FAIL; - lzw_dict_reset(&state); - } - - prefix = suffix; - } - else - prefix = code; - } - - if (!lzw_output_code(&state, prefix)) - return E_FAIL; - if (!lzw_output_eof_code(&state)) - return E_FAIL; - if (!lzw_flush_bits(&state)) - return E_FAIL; - } - - return flush_output_data(&out) ? S_OK : E_FAIL; -} - -static HRESULT WINAPI GifFrameEncode_Commit(IWICBitmapFrameEncode *iface) -{ - GifFrameEncode *This = impl_from_IWICBitmapFrameEncode(iface); - HRESULT hr; - - TRACE("%p\n", iface); - - EnterCriticalSection(&This->encoder->lock); - - if (This->image_data && This->lines == This->height && !This->committed) - { - BYTE gif_palette[256][3]; - - hr = S_OK; - - if (!This->encoder->info_written) - { - struct logical_screen_descriptor lsd; - - /* Logical Screen Descriptor */ - memcpy(lsd.signature, "GIF89a", 6); - lsd.width = This->width; - lsd.height = This->height; - lsd.packed = 0; - if (This->encoder->colors) - lsd.packed |= 0x80; /* global color table flag */ - lsd.packed |= 0x07 << 4; /* color resolution */ - lsd.packed |= 0x07; /* global color table size */ - lsd.background_color_index = 0; /* FIXME */ - lsd.pixel_aspect_ratio = 0; - hr = IStream_Write(This->encoder->stream, &lsd, sizeof(lsd), NULL); - if (hr == S_OK && This->encoder->colors) - { - UINT i; - - /* Global Color Table */ - memset(gif_palette, 0, sizeof(gif_palette)); - for (i = 0; i < This->encoder->colors; i++) - { - gif_palette[i][0] = (This->encoder->palette[i] >> 16) & 0xff; - gif_palette[i][1] = (This->encoder->palette[i] >> 8) & 0xff; - gif_palette[i][2] = This->encoder->palette[i] & 0xff; - } - hr = IStream_Write(This->encoder->stream, gif_palette, sizeof(gif_palette), NULL); - } - - /* FIXME: write GCE, APE, etc. GIF extensions */ - - if (hr == S_OK) - This->encoder->info_written = TRUE; - } - - if (hr == S_OK) - { - char image_separator = 0x2c; - - hr = IStream_Write(This->encoder->stream, &image_separator, sizeof(image_separator), NULL); - if (hr == S_OK) - { - struct image_descriptor imd; - - /* Image Descriptor */ - imd.left = 0; - imd.top = 0; - imd.width = This->width; - imd.height = This->height; - imd.packed = 0; - if (This->colors) - { - imd.packed |= 0x80; /* local color table flag */ - imd.packed |= 0x07; /* local color table size */ - } - /* FIXME: interlace flag */ - hr = IStream_Write(This->encoder->stream, &imd, sizeof(imd), NULL); - if (hr == S_OK && This->colors) - { - UINT i; - - /* Local Color Table */ - memset(gif_palette, 0, sizeof(gif_palette)); - for (i = 0; i < This->colors; i++) - { - gif_palette[i][0] = (This->palette[i] >> 16) & 0xff; - gif_palette[i][1] = (This->palette[i] >> 8) & 0xff; - gif_palette[i][2] = This->palette[i] & 0xff; - } - hr = IStream_Write(This->encoder->stream, gif_palette, sizeof(gif_palette), NULL); - if (hr == S_OK) - { - /* Image Data */ - hr = gif_compress(This->encoder->stream, This->image_data, This->width * This->height); - if (hr == S_OK) - This->committed = TRUE; - } - } - } - } - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->encoder->lock); - return hr; -} - -static HRESULT WINAPI GifFrameEncode_GetMetadataQueryWriter(IWICBitmapFrameEncode *iface, IWICMetadataQueryWriter **writer) -{ - FIXME("%p, %p: stub\n", iface, writer); - return E_NOTIMPL; -} - -static const IWICBitmapFrameEncodeVtbl GifFrameEncode_Vtbl = -{ - GifFrameEncode_QueryInterface, - GifFrameEncode_AddRef, - GifFrameEncode_Release, - GifFrameEncode_Initialize, - GifFrameEncode_SetSize, - GifFrameEncode_SetResolution, - GifFrameEncode_SetPixelFormat, - GifFrameEncode_SetColorContexts, - GifFrameEncode_SetPalette, - GifFrameEncode_SetThumbnail, - GifFrameEncode_WritePixels, - GifFrameEncode_WriteSource, - GifFrameEncode_Commit, - GifFrameEncode_GetMetadataQueryWriter -}; - -static HRESULT WINAPI GifEncoder_QueryInterface(IWICBitmapEncoder *iface, REFIID iid, void **ppv) -{ - TRACE("%p,%s,%p\n", iface, debugstr_guid(iid), ppv); - - if (!ppv) return E_INVALIDARG; - - if (IsEqualIID(&IID_IUnknown, iid) || - IsEqualIID(&IID_IWICBitmapEncoder, iid)) - { - IWICBitmapEncoder_AddRef(iface); - *ppv = iface; - return S_OK; - } - - *ppv = NULL; - return E_NOINTERFACE; -} - -static ULONG WINAPI GifEncoder_AddRef(IWICBitmapEncoder *iface) -{ - GifEncoder *This = impl_from_IWICBitmapEncoder(iface); - ULONG ref = InterlockedIncrement(&This->ref); - - TRACE("%p -> %u\n", iface, ref); - return ref; -} - -static ULONG WINAPI GifEncoder_Release(IWICBitmapEncoder *iface) -{ - GifEncoder *This = impl_from_IWICBitmapEncoder(iface); - ULONG ref = InterlockedDecrement(&This->ref); - - TRACE("%p -> %u\n", iface, ref); - - if (!ref) - { - 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 GifEncoder_Initialize(IWICBitmapEncoder *iface, IStream *stream, WICBitmapEncoderCacheOption option) -{ - GifEncoder *This = impl_from_IWICBitmapEncoder(iface); - HRESULT hr; - - TRACE("%p,%p,%#x\n", iface, stream, option); - - if (!stream) return E_INVALIDARG; - - EnterCriticalSection(&This->lock); - - if (!This->initialized) - { - IStream_AddRef(stream); - This->stream = stream; - This->initialized = TRUE; - hr = S_OK; - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->lock); - - return hr; -} - -static HRESULT WINAPI GifEncoder_GetContainerFormat(IWICBitmapEncoder *iface, GUID *format) -{ - if (!format) return E_INVALIDARG; - - *format = GUID_ContainerFormatGif; - return S_OK; -} - -static HRESULT WINAPI GifEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info) -{ - IWICComponentInfo *comp_info; - HRESULT hr; - - TRACE("%p,%p\n", iface, info); - - if (!info) return E_INVALIDARG; - - hr = CreateComponentInfo(&CLSID_WICGifEncoder, &comp_info); - if (hr == S_OK) - { - hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info); - IWICComponentInfo_Release(comp_info); - } - return hr; -} - -static HRESULT WINAPI GifEncoder_SetColorContexts(IWICBitmapEncoder *iface, UINT count, IWICColorContext **context) -{ - FIXME("%p,%u,%p: stub\n", iface, count, context); - return E_NOTIMPL; -} - -static HRESULT WINAPI GifEncoder_SetPalette(IWICBitmapEncoder *iface, IWICPalette *palette) -{ - GifEncoder *This = impl_from_IWICBitmapEncoder(iface); - HRESULT hr; - - TRACE("%p,%p\n", iface, palette); - - if (!palette) return E_INVALIDARG; - - EnterCriticalSection(&This->lock); - - if (This->initialized) - hr = IWICPalette_GetColors(palette, 256, This->palette, &This->colors); - else - hr = WINCODEC_ERR_NOTINITIALIZED; - - LeaveCriticalSection(&This->lock); - return hr; -} - -static HRESULT WINAPI GifEncoder_SetThumbnail(IWICBitmapEncoder *iface, IWICBitmapSource *thumbnail) -{ - TRACE("%p,%p\n", iface, thumbnail); - return WINCODEC_ERR_UNSUPPORTEDOPERATION; -} - -static HRESULT WINAPI GifEncoder_SetPreview(IWICBitmapEncoder *iface, IWICBitmapSource *preview) -{ - TRACE("%p,%p\n", iface, preview); - return WINCODEC_ERR_UNSUPPORTEDOPERATION; -} - -static HRESULT WINAPI GifEncoder_CreateNewFrame(IWICBitmapEncoder *iface, IWICBitmapFrameEncode **frame, IPropertyBag2 **options) -{ - GifEncoder *This = impl_from_IWICBitmapEncoder(iface); - HRESULT hr; - - TRACE("%p,%p,%p\n", iface, frame, options); - - if (!frame) return E_INVALIDARG; - - EnterCriticalSection(&This->lock); - - if (This->initialized && !This->committed) - { - GifFrameEncode *ret = HeapAlloc(GetProcessHeap(), 0, sizeof(*ret)); - if (ret) - { - This->n_frames++; - - ret->IWICBitmapFrameEncode_iface.lpVtbl = &GifFrameEncode_Vtbl; - ret->ref = 1; - ret->encoder = This; - ret->initialized = FALSE; - ret->interlace = FALSE; /* FIXME: read from the properties */ - ret->committed = FALSE; - ret->width = 0; - ret->height = 0; - ret->lines = 0; - ret->xres = 0.0; - ret->yres = 0.0; - ret->colors = 0; - ret->image_data = NULL; - IWICBitmapEncoder_AddRef(iface); - *frame = &ret->IWICBitmapFrameEncode_iface; - - hr = S_OK; - - if (options) - { - hr = CreatePropertyBag2(NULL, 0, options); - if (hr != S_OK) - { - IWICBitmapFrameEncode_Release(*frame); - *frame = NULL; - } - } - } - else - hr = E_OUTOFMEMORY; - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->lock); - - return hr; - -} - -static HRESULT WINAPI GifEncoder_Commit(IWICBitmapEncoder *iface) -{ - GifEncoder *This = impl_from_IWICBitmapEncoder(iface); - HRESULT hr; - - TRACE("%p\n", iface); - - EnterCriticalSection(&This->lock); - - if (This->initialized && !This->committed) - { - char gif_trailer = 0x3b; - - /* FIXME: write text, comment GIF extensions */ - - hr = IStream_Write(This->stream, &gif_trailer, sizeof(gif_trailer), NULL); - if (hr == S_OK) - This->committed = TRUE; - } - else - hr = WINCODEC_ERR_WRONGSTATE; - - LeaveCriticalSection(&This->lock); - return hr; -} - -static HRESULT WINAPI GifEncoder_GetMetadataQueryWriter(IWICBitmapEncoder *iface, IWICMetadataQueryWriter **writer) -{ - FIXME("%p,%p: stub\n", iface, writer); - return E_NOTIMPL; -} - -static const IWICBitmapEncoderVtbl GifEncoder_Vtbl = -{ - GifEncoder_QueryInterface, - GifEncoder_AddRef, - GifEncoder_Release, - GifEncoder_Initialize, - GifEncoder_GetContainerFormat, - GifEncoder_GetEncoderInfo, - GifEncoder_SetColorContexts, - GifEncoder_SetPalette, - GifEncoder_SetThumbnail, - GifEncoder_SetPreview, - GifEncoder_CreateNewFrame, - GifEncoder_Commit, - GifEncoder_GetMetadataQueryWriter -}; - -HRESULT GifEncoder_CreateInstance(REFIID iid, void **ppv) -{ - GifEncoder *This; - HRESULT ret; - - TRACE("%s,%p\n", debugstr_guid(iid), ppv); - - *ppv = NULL; - - This = HeapAlloc(GetProcessHeap(), 0, sizeof(*This)); - if (!This) return E_OUTOFMEMORY; - - This->IWICBitmapEncoder_iface.lpVtbl = &GifEncoder_Vtbl; - This->ref = 1; - This->stream = NULL; - InitializeCriticalSection(&This->lock); - This->lock.DebugInfo->Spare[0] = (DWORD_PTR)(__FILE__ ": GifEncoder.lock"); - This->initialized = FALSE; - This->info_written = FALSE; - This->committed = FALSE; - This->n_frames = 0; - This->colors = 0; - - ret = IWICBitmapEncoder_QueryInterface(&This->IWICBitmapEncoder_iface, iid, ppv); - IWICBitmapEncoder_Release(&This->IWICBitmapEncoder_iface); - - return ret; -} diff --git a/dll/win32/windowscodecs/imgfactory.c b/dll/win32/windowscodecs/imgfactory.c index cfb7fc1bf1..623265762a 100644 --- a/dll/win32/windowscodecs/imgfactory.c +++ b/dll/win32/windowscodecs/imgfactory.c @@ -104,23 +104,22 @@ static HRESULT WINAPI ComponentFactory_CreateDecoderFromFilename( return hr; } -static HRESULT find_decoder(IStream *pIStream, const GUID *pguidVendor, - WICDecodeOptions metadataOptions, IWICBitmapDecoder **decoder) +static IWICBitmapDecoder *find_decoder(IStream *pIStream, const GUID *pguidVendor, + WICDecodeOptions metadataOptions) { IEnumUnknown *enumdecoders; IUnknown *unkdecoderinfo; IWICBitmapDecoderInfo *decoderinfo; + IWICBitmapDecoder *decoder = NULL; GUID vendor; HRESULT res; ULONG num_fetched; BOOL matches; - *decoder = NULL; - res = CreateComponentEnumerator(WICDecoder, WICComponentEnumerateDefault, &enumdecoders); - if (FAILED(res)) return res; + if (FAILED(res)) return NULL; - while (!*decoder) + while (!decoder) { res = IEnumUnknown_Next(enumdecoders, 1, &unkdecoderinfo, &num_fetched); @@ -145,21 +144,18 @@ static HRESULT find_decoder(IStream *pIStream, const GUID *pguidVendor, if (SUCCEEDED(res) && matches) { - res = IWICBitmapDecoderInfo_CreateInstance(decoderinfo, decoder); + res = IWICBitmapDecoderInfo_CreateInstance(decoderinfo, &decoder); /* FIXME: should use QueryCapability to choose a decoder */ if (SUCCEEDED(res)) { - res = IWICBitmapDecoder_Initialize(*decoder, pIStream, metadataOptions); + res = IWICBitmapDecoder_Initialize(decoder, pIStream, metadataOptions); if (FAILED(res)) { - IWICBitmapDecoder_Release(*decoder); - IWICBitmapDecoderInfo_Release(decoderinfo); - IUnknown_Release(unkdecoderinfo); - *decoder = NULL; - return res; + IWICBitmapDecoder_Release(decoder); + decoder = NULL; } } } @@ -175,7 +171,7 @@ static HRESULT find_decoder(IStream *pIStream, const GUID *pguidVendor, IEnumUnknown_Release(enumdecoders); - return WINCODEC_ERR_COMPONENTNOTFOUND; + return decoder; } static HRESULT WINAPI ComponentFactory_CreateDecoderFromStream( @@ -189,9 +185,9 @@ static HRESULT WINAPI ComponentFactory_CreateDecoderFromStream( metadataOptions, ppIDecoder); if (pguidVendor) - res = find_decoder(pIStream, pguidVendor, metadataOptions, &decoder); + decoder = find_decoder(pIStream, pguidVendor, metadataOptions); if (!decoder) - res = find_decoder(pIStream, NULL, metadataOptions, &decoder); + decoder = find_decoder(pIStream, NULL, metadataOptions); if (decoder) { @@ -206,17 +202,17 @@ static HRESULT WINAPI ComponentFactory_CreateDecoderFromStream( BYTE data[4]; ULONG bytesread; - WARN("failed to load from a stream %#x\n", res); + WARN("failed to load from a stream\n"); seek.QuadPart = 0; - if (IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL) == S_OK) - { - if (IStream_Read(pIStream, data, 4, &bytesread) == S_OK) - WARN("first %i bytes of stream=%x %x %x %x\n", bytesread, data[0], data[1], data[2], data[3]); - } + res = IStream_Seek(pIStream, seek, STREAM_SEEK_SET, NULL); + if (SUCCEEDED(res)) + res = IStream_Read(pIStream, data, 4, &bytesread); + if (SUCCEEDED(res)) + WARN("first %i bytes of stream=%x %x %x %x\n", bytesread, data[0], data[1], data[2], data[3]); } *ppIDecoder = NULL; - return res; + return WINCODEC_ERR_COMPONENTNOTFOUND; } } @@ -583,36 +579,12 @@ static HRESULT WINAPI ComponentFactory_CreateBitmapFromMemory(IWICComponentFacto UINT width, UINT height, REFWICPixelFormatGUID format, UINT stride, UINT size, BYTE *buffer, IWICBitmap **bitmap) { - HRESULT hr; - TRACE("(%p,%u,%u,%s,%u,%u,%p,%p\n", iface, width, height, debugstr_guid(format), stride, size, buffer, bitmap); if (!stride || !size || !buffer || !bitmap) return E_INVALIDARG; - hr = BitmapImpl_Create(width, height, stride, size, NULL, format, WICBitmapCacheOnLoad, bitmap); - if (SUCCEEDED(hr)) - { - IWICBitmapLock *lock; - - hr = IWICBitmap_Lock(*bitmap, NULL, WICBitmapLockWrite, &lock); - if (SUCCEEDED(hr)) - { - UINT buffersize; - BYTE *data; - - IWICBitmapLock_GetDataPointer(lock, &buffersize, &data); - memcpy(data, buffer, buffersize); - - IWICBitmapLock_Release(lock); - } - else - { - IWICBitmap_Release(*bitmap); - *bitmap = NULL; - } - } - return hr; + return BitmapImpl_Create(width, height, stride, size, buffer, format, WICBitmapCacheOnLoad, bitmap); } static BOOL get_16bpp_format(HBITMAP hbm, WICPixelFormatGUID *format) @@ -1188,50 +1160,3 @@ HRESULT ComponentFactory_CreateInstance(REFIID iid, void** ppv) return ret; } - -HRESULT WINAPI WICCreateBitmapFromSectionEx(UINT width, UINT height, - REFWICPixelFormatGUID format, HANDLE section, UINT stride, - UINT offset, WICSectionAccessLevel wicaccess, IWICBitmap **bitmap) -{ - DWORD access; - void *buffer; - HRESULT hr; - - TRACE("%u,%u,%s,%p,%u,%#x,%#x,%p\n", width, height, debugstr_guid(format), - section, stride, offset, wicaccess, bitmap); - - if (!width || !height || !section || !bitmap) return E_INVALIDARG; - - switch (wicaccess) - { - case WICSectionAccessLevelReadWrite: - access = FILE_MAP_READ | FILE_MAP_WRITE; - break; - - case WICSectionAccessLevelRead: - access = FILE_MAP_READ; - break; - - default: - FIXME("unsupported access %#x\n", wicaccess); - return E_INVALIDARG; - } - - buffer = MapViewOfFile(section, access, 0, offset, 0); - if (!buffer) return HRESULT_FROM_WIN32(GetLastError()); - - hr = BitmapImpl_Create(width, height, stride, 0, buffer, format, WICBitmapCacheOnLoad, bitmap); - if (FAILED(hr)) UnmapViewOfFile(buffer); - return hr; -} - -HRESULT WINAPI WICCreateBitmapFromSection(UINT width, UINT height, - REFWICPixelFormatGUID format, HANDLE section, - UINT stride, UINT offset, IWICBitmap **bitmap) -{ - TRACE("%u,%u,%s,%p,%u,%u,%p\n", width, height, debugstr_guid(format), - section, stride, offset, bitmap); - - return WICCreateBitmapFromSectionEx(width, height, format, section, - stride, offset, WICSectionAccessLevelRead, bitmap); -} diff --git a/dll/win32/windowscodecs/info.c b/dll/win32/windowscodecs/info.c index d3ea8754a2..63cdc07dbc 100644 --- a/dll/win32/windowscodecs/info.c +++ b/dll/win32/windowscodecs/info.c @@ -853,12 +853,8 @@ static HRESULT WINAPI BitmapEncoderInfo_GetMimeTypes(IWICBitmapEncoderInfo *ifac static HRESULT WINAPI BitmapEncoderInfo_GetFileExtensions(IWICBitmapEncoderInfo *iface, UINT cchFileExtensions, WCHAR *wzFileExtensions, UINT *pcchActual) { - BitmapEncoderInfo *This = impl_from_IWICBitmapEncoderInfo(iface); - - TRACE("(%p,%u,%p,%p)\n", iface, cchFileExtensions, wzFileExtensions, pcchActual); - - return ComponentInfo_GetStringValue(This->classkey, fileextensions_valuename, - cchFileExtensions, wzFileExtensions, pcchActual); + FIXME("(%p,%u,%p,%p): stub\n", iface, cchFileExtensions, wzFileExtensions, pcchActual); + return E_NOTIMPL; } static HRESULT WINAPI BitmapEncoderInfo_DoesSupportAnimation(IWICBitmapEncoderInfo *iface, @@ -2269,12 +2265,6 @@ HRESULT CreateComponentEnumerator(DWORD componentTypes, DWORD options, IEnumUnkn return hr; } -static BOOL is_1bpp_format(const WICPixelFormatGUID *format) -{ - return IsEqualGUID(format, &GUID_WICPixelFormatBlackWhite) || - IsEqualGUID(format, &GUID_WICPixelFormat1bppIndexed); -} - HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitmapSource *pISrc, IWICBitmapSource **ppIDst) { HRESULT res; @@ -2287,12 +2277,10 @@ HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitma BOOL canconvert; ULONG num_fetched; - TRACE("%s,%p,%p\n", debugstr_guid(dstFormat), pISrc, ppIDst); - res = IWICBitmapSource_GetPixelFormat(pISrc, &srcFormat); if (FAILED(res)) return res; - if (IsEqualGUID(&srcFormat, dstFormat) || (is_1bpp_format(&srcFormat) && is_1bpp_format(dstFormat))) + if (IsEqualGUID(&srcFormat, dstFormat)) { IWICBitmapSource_AddRef(pISrc); *ppIDst = pISrc; @@ -2329,7 +2317,7 @@ HRESULT WINAPI WICConvertBitmapSource(REFWICPixelFormatGUID dstFormat, IWICBitma if (SUCCEEDED(res) && canconvert) res = IWICFormatConverter_Initialize(converter, pISrc, dstFormat, WICBitmapDitherTypeNone, - NULL, 0.0, WICBitmapPaletteTypeMedianCut); + NULL, 0.0, WICBitmapPaletteTypeCustom); if (FAILED(res) || !canconvert) { diff --git a/dll/win32/windowscodecs/jpegformat.c b/dll/win32/windowscodecs/jpegformat.c index ecbfc01c3c..cfb84c36aa 100644 --- a/dll/win32/windowscodecs/jpegformat.c +++ b/dll/win32/windowscodecs/jpegformat.c @@ -137,7 +137,6 @@ typedef struct { struct jpeg_error_mgr jerr; struct jpeg_source_mgr source_mgr; BYTE source_buffer[1024]; - UINT bpp, stride; BYTE *image_data; CRITICAL_SECTION lock; } JpegDecoder; @@ -286,8 +285,6 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream * int ret; LARGE_INTEGER seek; jmp_buf jmpbuf; - UINT data_size, i; - TRACE("(%p,%p,%u)\n", iface, pIStream, cacheOptions); EnterCriticalSection(&This->lock); @@ -366,55 +363,6 @@ static HRESULT WINAPI JpegDecoder_Initialize(IWICBitmapDecoder *iface, IStream * return E_FAIL; } - if (This->cinfo.out_color_space == JCS_GRAYSCALE) This->bpp = 8; - else if (This->cinfo.out_color_space == JCS_CMYK) This->bpp = 32; - else This->bpp = 24; - - This->stride = (This->bpp * This->cinfo.output_width + 7) / 8; - data_size = This->stride * This->cinfo.output_height; - - This->image_data = HeapAlloc(GetProcessHeap(), 0, data_size); - if (!This->image_data) - { - LeaveCriticalSection(&This->lock); - return E_OUTOFMEMORY; - } - - while (This->cinfo.output_scanline < This->cinfo.output_height) - { - UINT first_scanline = This->cinfo.output_scanline; - UINT max_rows; - JSAMPROW out_rows[4]; - JDIMENSION ret; - - max_rows = min(This->cinfo.output_height-first_scanline, 4); - for (i=0; i<max_rows; i++) - out_rows[i] = This->image_data + This->stride * (first_scanline+i); - - ret = pjpeg_read_scanlines(&This->cinfo, out_rows, max_rows); - if (ret == 0) - { - ERR("read_scanlines failed\n"); - LeaveCriticalSection(&This->lock); - return E_FAIL; - } - } - - if (This->bpp == 24) - { - /* libjpeg gives us RGB data and we want BGR, so byteswap the data */ - reverse_bgr8(3, This->image_data, - This->cinfo.output_width, This->cinfo.output_height, - This->stride); - } - - if (This->cinfo.out_color_space == JCS_CMYK && This->cinfo.saw_Adobe_marker) - { - /* Adobe JPEG's have inverted CMYK data. */ - for (i=0; i<data_size; i++) - This->image_data[i] ^= 0xff; - } - This->initialized = TRUE; LeaveCriticalSection(&This->lock); @@ -457,14 +405,10 @@ static HRESULT WINAPI JpegDecoder_CopyPalette(IWICBitmapDecoder *iface, } static HRESULT WINAPI JpegDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, - IWICMetadataQueryReader **reader) + IWICMetadataQueryReader **ppIMetadataQueryReader) { - FIXME("(%p,%p): stub\n", iface, reader); - - if (!reader) return E_INVALIDARG; - - *reader = NULL; - return WINCODEC_ERR_UNSUPPORTEDOPERATION; + FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); + return E_NOTIMPL; } static HRESULT WINAPI JpegDecoder_GetPreview(IWICBitmapDecoder *iface, @@ -635,11 +579,98 @@ static HRESULT WINAPI JpegDecoder_Frame_CopyPixels(IWICBitmapFrameDecode *iface, const WICRect *prc, UINT cbStride, UINT cbBufferSize, BYTE *pbBuffer) { JpegDecoder *This = impl_from_IWICBitmapFrameDecode(iface); - + UINT bpp; + UINT stride; + UINT data_size; + UINT max_row_needed; + jmp_buf jmpbuf; + WICRect rect; TRACE("(%p,%p,%u,%u,%p)\n", iface, prc, cbStride, cbBufferSize, pbBuffer); - return copy_pixels(This->bpp, This->image_data, - This->cinfo.output_width, This->cinfo.output_height, This->stride, + if (!prc) + { + rect.X = 0; + rect.Y = 0; + rect.Width = This->cinfo.output_width; + rect.Height = This->cinfo.output_height; + prc = ▭ + } + else + { + if (prc->X < 0 || prc->Y < 0 || prc->X+prc->Width > This->cinfo.output_width || + prc->Y+prc->Height > This->cinfo.output_height) + return E_INVALIDARG; + } + + if (This->cinfo.out_color_space == JCS_GRAYSCALE) bpp = 8; + else if (This->cinfo.out_color_space == JCS_CMYK) bpp = 32; + else bpp = 24; + + stride = bpp * This->cinfo.output_width; + data_size = stride * This->cinfo.output_height; + + max_row_needed = prc->Y + prc->Height; + if (max_row_needed > This->cinfo.output_height) return E_INVALIDARG; + + EnterCriticalSection(&This->lock); + + if (!This->image_data) + { + This->image_data = HeapAlloc(GetProcessHeap(), 0, data_size); + if (!This->image_data) + { + LeaveCriticalSection(&This->lock); + return E_OUTOFMEMORY; + } + } + + This->cinfo.client_data = jmpbuf; + + if (setjmp(jmpbuf)) + { + LeaveCriticalSection(&This->lock); + return E_FAIL; + } + + while (max_row_needed > This->cinfo.output_scanline) + { + UINT first_scanline = This->cinfo.output_scanline; + UINT max_rows; + JSAMPROW out_rows[4]; + UINT i; + JDIMENSION ret; + + max_rows = min(This->cinfo.output_height-first_scanline, 4); + for (i=0; i<max_rows; i++) + out_rows[i] = This->image_data + stride * (first_scanline+i); + + ret = pjpeg_read_scanlines(&This->cinfo, out_rows, max_rows); + + if (ret == 0) + { + ERR("read_scanlines failed\n"); + LeaveCriticalSection(&This->lock); + return E_FAIL; + } + + if (bpp == 24) + { + /* libjpeg gives us RGB data and we want BGR, so byteswap the data */ + reverse_bgr8(3, This->image_data + stride * first_scanline, + This->cinfo.output_width, This->cinfo.output_scanline - first_scanline, + stride); + } + + if (This->cinfo.out_color_space == JCS_CMYK && This->cinfo.saw_Adobe_marker) + /* Adobe JPEG's have inverted CMYK data. */ + for (i=0; i<data_size; i++) + This->image_data[i] ^= 0xff; + } + + LeaveCriticalSection(&This->lock); + + return copy_pixels(bpp, This->image_data, + This->cinfo.output_width, This->cinfo.output_height, stride, prc, cbStride, cbBufferSize, pbBuffer); } @@ -1344,22 +1375,11 @@ static HRESULT WINAPI JpegEncoder_GetContainerFormat(IWICBitmapEncoder *iface, return E_NOTIMPL; } -static HRESULT WINAPI JpegEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info) +static HRESULT WINAPI JpegEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, + IWICBitmapEncoderInfo **ppIEncoderInfo) { - IWICComponentInfo *comp_info; - HRESULT hr; - - TRACE("%p,%p\n", iface, info); - - if (!info) return E_INVALIDARG; - - hr = CreateComponentInfo(&CLSID_WICJpegEncoder, &comp_info); - if (hr == S_OK) - { - hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info); - IWICComponentInfo_Release(comp_info); - } - return hr; + FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo); + return E_NOTIMPL; } static HRESULT WINAPI JpegEncoder_SetColorContexts(IWICBitmapEncoder *iface, @@ -1439,14 +1459,11 @@ static HRESULT WINAPI JpegEncoder_CreateNewFrame(IWICBitmapEncoder *iface, opts[5].vt = VT_BOOL; opts[5].dwType = PROPBAG2_TYPE_DATA; - if (ppIEncoderOptions) + hr = CreatePropertyBag2(opts, 6, ppIEncoderOptions); + if (FAILED(hr)) { - hr = CreatePropertyBag2(opts, 6, ppIEncoderOptions); - if (FAILED(hr)) - { - LeaveCriticalSection(&This->lock); - return hr; - } + LeaveCriticalSection(&This->lock); + return hr; } This->frame_count = 1; diff --git a/dll/win32/windowscodecs/metadatahandler.c b/dll/win32/windowscodecs/metadatahandler.c index 25f4314720..dff5ed3c7f 100644 --- a/dll/win32/windowscodecs/metadatahandler.c +++ b/dll/win32/windowscodecs/metadatahandler.c @@ -704,7 +704,7 @@ static int tag_to_vt(SHORT tag) static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, MetadataItem *item, BOOL native_byte_order) { - ULONG count, value, i; + ULONG count, value, i, bytesread; SHORT type; LARGE_INTEGER pos; HRESULT hr; @@ -746,7 +746,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, item->value.vt |= VT_VECTOR; item->value.u.caub.cElems = count; - item->value.u.caub.pElems = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count); + item->value.u.caub.pElems = HeapAlloc(GetProcessHeap(), 0, count); if (!item->value.u.caub.pElems) return E_OUTOFMEMORY; pos.QuadPart = value; @@ -756,8 +756,9 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, HeapFree(GetProcessHeap(), 0, item->value.u.caub.pElems); return hr; } - hr = IStream_Read(input, item->value.u.caub.pElems, count, NULL); - if (FAILED(hr)) + hr = IStream_Read(input, item->value.u.caub.pElems, count, &bytesread); + if (bytesread != count) hr = E_FAIL; + if (hr != S_OK) { HeapFree(GetProcessHeap(), 0, item->value.u.caub.pElems); return hr; @@ -790,7 +791,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, item->value.vt |= VT_VECTOR; item->value.u.caui.cElems = count; - item->value.u.caui.pElems = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * 2); + item->value.u.caui.pElems = HeapAlloc(GetProcessHeap(), 0, count * 2); if (!item->value.u.caui.pElems) return E_OUTOFMEMORY; pos.QuadPart = value; @@ -800,8 +801,9 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, HeapFree(GetProcessHeap(), 0, item->value.u.caui.pElems); return hr; } - hr = IStream_Read(input, item->value.u.caui.pElems, count * 2, NULL); - if (FAILED(hr)) + hr = IStream_Read(input, item->value.u.caui.pElems, count * 2, &bytesread); + if (bytesread != count * 2) hr = E_FAIL; + if (hr != S_OK) { HeapFree(GetProcessHeap(), 0, item->value.u.caui.pElems); return hr; @@ -822,7 +824,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, item->value.vt |= VT_VECTOR; item->value.u.caul.cElems = count; - item->value.u.caul.pElems = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * 4); + item->value.u.caul.pElems = HeapAlloc(GetProcessHeap(), 0, count * 4); if (!item->value.u.caul.pElems) return E_OUTOFMEMORY; pos.QuadPart = value; @@ -832,8 +834,9 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, HeapFree(GetProcessHeap(), 0, item->value.u.caul.pElems); return hr; } - hr = IStream_Read(input, item->value.u.caul.pElems, count * 4, NULL); - if (FAILED(hr)) + hr = IStream_Read(input, item->value.u.caul.pElems, count * 4, &bytesread); + if (bytesread != count * 4) hr = E_FAIL; + if (hr != S_OK) { HeapFree(GetProcessHeap(), 0, item->value.u.caul.pElems); return hr; @@ -859,7 +862,8 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, hr = IStream_Seek(input, pos, SEEK_SET, NULL); if (FAILED(hr)) return hr; - hr = IStream_Read(input, &ull, sizeof(ull), NULL); + hr = IStream_Read(input, &ull, sizeof(ull), &bytesread); + if (bytesread != sizeof(ull)) hr = E_FAIL; if (hr != S_OK) return hr; item->value.u.uhVal.QuadPart = ull; @@ -877,7 +881,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, { item->value.vt |= VT_VECTOR; item->value.u.cauh.cElems = count; - item->value.u.cauh.pElems = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count * 8); + item->value.u.cauh.pElems = HeapAlloc(GetProcessHeap(), 0, count * 8); if (!item->value.u.cauh.pElems) return E_OUTOFMEMORY; pos.QuadPart = value; @@ -887,8 +891,9 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, HeapFree(GetProcessHeap(), 0, item->value.u.cauh.pElems); return hr; } - hr = IStream_Read(input, item->value.u.cauh.pElems, count * 8, NULL); - if (FAILED(hr)) + hr = IStream_Read(input, item->value.u.cauh.pElems, count * 8, &bytesread); + if (bytesread != count * 8) hr = E_FAIL; + if (hr != S_OK) { HeapFree(GetProcessHeap(), 0, item->value.u.cauh.pElems); return hr; @@ -906,7 +911,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, } break; case IFD_ASCII: - item->value.u.pszVal = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count + 1); + item->value.u.pszVal = HeapAlloc(GetProcessHeap(), 0, count + 1); if (!item->value.u.pszVal) return E_OUTOFMEMORY; if (count <= 4) @@ -924,8 +929,9 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, HeapFree(GetProcessHeap(), 0, item->value.u.pszVal); return hr; } - hr = IStream_Read(input, item->value.u.pszVal, count, NULL); - if (FAILED(hr)) + hr = IStream_Read(input, item->value.u.pszVal, count, &bytesread); + if (bytesread != count) hr = E_FAIL; + if (hr != S_OK) { HeapFree(GetProcessHeap(), 0, item->value.u.pszVal); return hr; @@ -940,7 +946,7 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, break; } - item->value.u.blob.pBlobData = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, count); + item->value.u.blob.pBlobData = HeapAlloc(GetProcessHeap(), 0, count); if (!item->value.u.blob.pBlobData) return E_OUTOFMEMORY; item->value.u.blob.cbSize = count; @@ -959,8 +965,9 @@ static HRESULT load_IFD_entry(IStream *input, const struct IFD_entry *entry, HeapFree(GetProcessHeap(), 0, item->value.u.blob.pBlobData); return hr; } - hr = IStream_Read(input, item->value.u.blob.pBlobData, count, NULL); - if (FAILED(hr)) + hr = IStream_Read(input, item->value.u.blob.pBlobData, count, &bytesread); + if (bytesread != count) hr = E_FAIL; + if (hr != S_OK) { HeapFree(GetProcessHeap(), 0, item->value.u.blob.pBlobData); return hr; diff --git a/dll/win32/windowscodecs/palette.c b/dll/win32/windowscodecs/palette.c index d31cb554d8..89b10b7ba9 100644 --- a/dll/win32/windowscodecs/palette.c +++ b/dll/win32/windowscodecs/palette.c @@ -1,7 +1,6 @@ /* * Copyright 2009 Vincent Povirk for CodeWeavers - * Copyright 2012,2016 Dmitry Timoshkov - * Copyright 2016 Sebastian Lackner + * Copyright 2012 Dmitry Timoshkov * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -432,279 +431,11 @@ static HRESULT WINAPI PaletteImpl_InitializeCustom(IWICPalette *iface, return S_OK; } -#define R_COUNT (1 << 5) -#define R_SHIFT (8 - 5) -#define R_SCALE 2 - -#define G_COUNT (1 << 6) -#define G_SHIFT (8 - 6) -#define G_SCALE 3 - -#define B_COUNT (1 << 5) -#define B_SHIFT (8 - 5) -#define B_SCALE 1 - -struct histogram -{ - unsigned int data[R_COUNT][G_COUNT][B_COUNT]; -}; - -struct box -{ - int r_min, r_max; - int g_min, g_max; - int b_min, b_max; - unsigned int count; - unsigned int score; -}; - -/* count nonzero elements in the histogram range [r_min, r_max] x [g_min, g_max] x [b_min, b_max] */ -static inline unsigned int histogram_count(struct histogram *h, int r_min, int r_max, - int g_min, int g_max, int b_min, int b_max) -{ - unsigned int count = 0; - int r, g, b; - for (r = r_min; r <= r_max; r++) - for (g = g_min; g <= g_max; g++) - for (b = b_min; b <= b_max; b++) - if (h->data[r][g][b] != 0) count++; - return count; -} - -/* compute weighted average color in the range [r_min, r_max] x [g_min, g_max] x [b_min, b_max] */ -static unsigned int histogram_color(struct histogram *h, int r_min, int r_max, - int g_min, int g_max, int b_min, int b_max) -{ - unsigned long long r_sum = 0, g_sum = 0, b_sum = 0; - unsigned int tmp, count = 0; - int r, g, b; - - for (r = r_min; r <= r_max; r++) - for (g = g_min; g <= g_max; g++) - for (b = b_min; b <= b_max; b++) - { - if (!(tmp = h->data[r][g][b])) continue; - r_sum += ((r << R_SHIFT) + ((1 << R_SHIFT) / 2)) * tmp; - g_sum += ((g << G_SHIFT) + ((1 << G_SHIFT) / 2)) * tmp; - b_sum += ((b << B_SHIFT) + ((1 << B_SHIFT) / 2)) * tmp; - count += tmp; - } - - return ((b_sum + (count / 2)) / count) | - ((g_sum + (count / 2)) / count) << 8 | - ((r_sum + (count / 2)) / count) << 16 | 0xff000000; -} - -/* same as histogram_count */ -static inline unsigned int box_count(struct histogram *h, struct box *b) -{ - return histogram_count(h, b->r_min, b->r_max, b->g_min, b->g_max, b->b_min, b->b_max); -} - -/* same as histogram_color */ -static inline unsigned int box_color(struct histogram *h, struct box *b) -{ - return histogram_color(h, b->r_min, b->r_max, b->g_min, b->g_max, b->b_min, b->b_max); -} - -/* compute score used to determine best split (also called "volume") */ -static inline unsigned int box_score(struct box *b) -{ - unsigned int tmp, sum = 0; - tmp = ((b->r_max - b->r_min) << R_SHIFT) * R_SCALE; sum += tmp * tmp; - tmp = ((b->g_max - b->g_min) << G_SHIFT) * G_SCALE; sum += tmp * tmp; - tmp = ((b->b_max - b->b_min) << B_SHIFT) * B_SCALE; sum += tmp * tmp; - return sum; -} - -/* attempt to shrink a box */ -static void shrink_box(struct histogram *h, struct box *b) -{ - int i; - for (i = b->r_min; i <= b->r_max; i++) - if (histogram_count(h, i, i, b->g_min, b->g_max, b->b_min, b->b_max)) { b->r_min = i; break; } - for (i = b->r_max; i >= b->r_min; i--) - if (histogram_count(h, i, i, b->g_min, b->g_max, b->b_min, b->b_max)) { b->r_max = i; break; } - for (i = b->g_min; i <= b->g_max; i++) - if (histogram_count(h, b->r_min, b->r_max, i, i, b->b_min, b->b_max)) { b->g_min = i; break; } - for (i = b->g_max; i >= b->g_min; i--) - if (histogram_count(h, b->r_min, b->r_max, i, i, b->b_min, b->b_max)) { b->g_max = i; break; } - for (i = b->b_min; i <= b->b_max; i++) - if (histogram_count(h, b->r_min, b->r_max, b->g_min, b->g_max, i, i)) { b->b_min = i; break; } - for (i = b->b_max; i >= b->b_min; i--) - if (histogram_count(h, b->r_min, b->r_max, b->g_min, b->g_max, i, i)) { b->b_max = i; break; } - b->count = box_count(h, b); - b->score = box_score(b); -} - -/* helper for split_box */ -static inline void set_avg(int *min, int *max) -{ - int avg = (*min + *max) / 2; - *min = avg + 1; - *max = avg; -} - -/* split a box based on the best axis */ -static void split_box(struct histogram *h, struct box *b1, struct box *b2) -{ - int r = ((b1->r_max - b1->r_min) << R_SHIFT) * R_SCALE; - int g = ((b1->g_max - b1->g_min) << G_SHIFT) * G_SCALE; - int b = ((b1->b_max - b1->b_min) << B_SHIFT) * B_SCALE; - - *b2 = *b1; - - if (r > g) - { - if (b > r) set_avg(&b1->b_min, &b2->b_max); - else set_avg(&b1->r_min, &b2->r_max); - } - else - { - if (b > g) set_avg(&b1->b_min, &b2->b_max); - else set_avg(&b1->g_min, &b2->g_max); - } - - shrink_box(h, b1); - shrink_box(h, b2); -} - -/* find box suitable for split based on count */ -static struct box *find_box_max_count(struct box *b, int count) -{ - struct box *best = NULL; - for (; count--; b++) - if (b->score && (!best || b->count > best->count)) best = b; - return best; -} - -/* find box suitable for split based on score */ -static struct box *find_box_max_score(struct box *b, int count) -{ - struct box *best = NULL; - for (; count--; b++) - if (b->score && (!best || b->score > best->score)) best = b; - return best; -} - -/* compute color map with at most 'desired' colors - * image must be in 24bpp BGR format and colors are returned in 0xAARRGGBB format */ -static int median_cut(unsigned char *image, unsigned int width, unsigned int height, - unsigned int stride, int desired, unsigned int *colors) -{ - struct box boxes[256]; - struct histogram *h; - unsigned int x, y; - unsigned char *p; - struct box *b1, *b2; - int numboxes, i; - - if (!(h = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*h)))) - return 0; - - for (y = 0; y < height; y++) - for (x = 0, p = image + y * stride; x < width; x++, p += 3) - h->data[p[2] >> R_SHIFT][p[1] >> G_SHIFT][p[0] >> B_SHIFT]++; - - numboxes = 1; - boxes[0].r_min = 0; boxes[0].r_max = R_COUNT - 1; - boxes[0].g_min = 0; boxes[0].g_max = G_COUNT - 1; - boxes[0].b_min = 0; boxes[0].b_max = B_COUNT - 1; - shrink_box(h, &boxes[0]); - - while (numboxes <= desired / 2) - { - if (!(b1 = find_box_max_count(boxes, numboxes))) break; - b2 = &boxes[numboxes++]; - split_box(h, b1, b2); - } - while (numboxes < desired) - { - if (!(b1 = find_box_max_score(boxes, numboxes))) break; - b2 = &boxes[numboxes++]; - split_box(h, b1, b2); - } - - for (i = 0; i < numboxes; i++) - colors[i] = box_color(h, &boxes[i]); - - HeapFree(GetProcessHeap(), 0, h); - return numboxes; -} - - -static HRESULT WINAPI PaletteImpl_InitializeFromBitmap(IWICPalette *palette, - IWICBitmapSource *source, UINT desired, BOOL add_transparent) +static HRESULT WINAPI PaletteImpl_InitializeFromBitmap(IWICPalette *iface, + IWICBitmapSource *pISurface, UINT colorCount, BOOL fAddTransparentColor) { - IWICImagingFactory *factory = NULL; - IWICBitmap *rgb24_bitmap = NULL; - IWICBitmapSource *rgb24_source; - IWICBitmapLock *lock = NULL; - WICPixelFormatGUID format; - HRESULT hr; - UINT width, height, stride, size, actual_number_of_colors; - BYTE *src; - WICColor colors[256]; - - TRACE("(%p,%p,%u,%d)\n", palette, source, desired, add_transparent); - - if (!source || desired < 2 || desired > 256) - return E_INVALIDARG; - - hr = IWICBitmapSource_GetPixelFormat(source, &format); - if (hr != S_OK) return hr; - - /* For interoperability with gdiplus where PixelFormat24bppRGB actully stored - * as BGR (and there is no a corresponding RGB format) we have to use 24bppBGR - * to avoid format conversions. - */ - if (!IsEqualGUID(&format, &GUID_WICPixelFormat24bppBGR)) - { - hr = WICConvertBitmapSource(&GUID_WICPixelFormat24bppBGR, source, &rgb24_source); - if (hr != S_OK) return hr; - } - else - rgb24_source = source; - - hr = ComponentFactory_CreateInstance(&IID_IWICImagingFactory, (void **)&factory); - if (hr != S_OK) goto fail; - - hr = IWICImagingFactory_CreateBitmapFromSource(factory, rgb24_source, WICBitmapCacheOnLoad, &rgb24_bitmap); - if (hr != S_OK) goto fail; - - hr = IWICBitmap_Lock(rgb24_bitmap, NULL, WICBitmapLockRead, &lock); - if (hr != S_OK) goto fail; - - IWICBitmapLock_GetSize(lock, &width, &height); - IWICBitmapLock_GetStride(lock, &stride); - IWICBitmapLock_GetDataPointer(lock, &size, &src); - - actual_number_of_colors = median_cut(src, width, height, stride, add_transparent ? desired - 1 : desired, colors); - TRACE("actual number of colors: %u\n", actual_number_of_colors); - - if (actual_number_of_colors) - { - if (add_transparent) colors[actual_number_of_colors++] = 0; - - hr = IWICPalette_InitializeCustom(palette, colors, actual_number_of_colors); - } - else - hr = E_OUTOFMEMORY; - -fail: - if (lock) - IWICBitmapLock_Release(lock); - - if (rgb24_bitmap) - IWICBitmap_Release(rgb24_bitmap); - - if (factory) - IWICImagingFactory_Release(factory); - - if (rgb24_source != source) - IWICBitmapSource_Release(rgb24_source); - - return hr; + FIXME("(%p,%p,%u,%i): stub\n", iface, pISurface, colorCount, fAddTransparentColor); + return E_NOTIMPL; } static HRESULT WINAPI PaletteImpl_InitializeFromPalette(IWICPalette *iface, diff --git a/dll/win32/windowscodecs/pngformat.c b/dll/win32/windowscodecs/pngformat.c index 175642b295..6946721b77 100644 --- a/dll/win32/windowscodecs/pngformat.c +++ b/dll/win32/windowscodecs/pngformat.c @@ -19,8 +19,6 @@ #include "wincodecs_private.h" -#include <winerror.h> - #ifdef HAVE_PNG_H #include <png.h> #endif @@ -565,8 +563,6 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p int num_trans; png_uint_32 transparency; png_color_16p trans_values; - png_colorp png_palette; - int num_palette; jmp_buf jmpbuf; BYTE chunk_type[4]; ULONG chunk_size; @@ -609,7 +605,7 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p ppng_destroy_read_struct(&This->png_ptr, &This->info_ptr, &This->end_info); HeapFree(GetProcessHeap(), 0, row_pointers); This->png_ptr = NULL; - hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT; + hr = E_FAIL; goto end; } ppng_set_error_fn(This->png_ptr, jmpbuf, user_error_fn, user_warning_fn); @@ -633,37 +629,18 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p /* check for color-keyed alpha */ transparency = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans, &num_trans, &trans_values); - if (!ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette)) - num_palette = 0; - - TRACE("color_type %d, bit_depth %d, transparency %d, num_palette %d\n", - color_type, bit_depth, transparency, num_palette); + if (transparency && (color_type == PNG_COLOR_TYPE_RGB || + (color_type == PNG_COLOR_TYPE_GRAY && bit_depth == 16))) + { + /* expand to RGBA */ + if (color_type == PNG_COLOR_TYPE_GRAY) + ppng_set_gray_to_rgb(This->png_ptr); + ppng_set_tRNS_to_alpha(This->png_ptr); + color_type = PNG_COLOR_TYPE_RGB_ALPHA; + } switch (color_type) { - case PNG_COLOR_TYPE_GRAY: - This->bpp = bit_depth; - switch (bit_depth) - { - case 1: - This->format = num_palette ? &GUID_WICPixelFormat1bppIndexed : &GUID_WICPixelFormatBlackWhite; - break; - case 2: - This->format = num_palette ? &GUID_WICPixelFormat2bppIndexed : &GUID_WICPixelFormat2bppGray; - break; - case 4: - This->format = num_palette ? &GUID_WICPixelFormat4bppIndexed : &GUID_WICPixelFormat4bppGray; - break; - case 8: - This->format = num_palette ? &GUID_WICPixelFormat8bppIndexed : &GUID_WICPixelFormat8bppGray; - break; - case 16: This->format = &GUID_WICPixelFormat16bppGray; break; - default: - ERR("invalid grayscale bit depth: %i\n", bit_depth); - hr = WINCODEC_ERR_UNKNOWNIMAGEFORMAT; - goto end; - } - break; case PNG_COLOR_TYPE_GRAY_ALPHA: /* WIC does not support grayscale alpha formats so use RGBA */ ppng_set_gray_to_rgb(This->png_ptr); @@ -683,6 +660,25 @@ static HRESULT WINAPI PngDecoder_Initialize(IWICBitmapDecoder *iface, IStream *p goto end; } break; + case PNG_COLOR_TYPE_GRAY: + This->bpp = bit_depth; + if (!transparency) + { + switch (bit_depth) + { + case 1: This->format = &GUID_WICPixelFormatBlackWhite; break; + case 2: This->format = &GUID_WICPixelFormat2bppGray; break; + case 4: This->format = &GUID_WICPixelFormat4bppGray; break; + case 8: This->format = &GUID_WICPixelFormat8bppGray; break; + case 16: This->format = &GUID_WICPixelFormat16bppGray; break; + default: + ERR("invalid grayscale bit depth: %i\n", bit_depth); + hr = E_FAIL; + goto end; + } + break; + } + /* else fall through */ case PNG_COLOR_TYPE_PALETTE: This->bpp = bit_depth; switch (bit_depth) @@ -840,14 +836,10 @@ static HRESULT WINAPI PngDecoder_CopyPalette(IWICBitmapDecoder *iface, } static HRESULT WINAPI PngDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, - IWICMetadataQueryReader **reader) + IWICMetadataQueryReader **ppIMetadataQueryReader) { - FIXME("(%p,%p): stub\n", iface, reader); - - if (!reader) return E_INVALIDARG; - - *reader = NULL; - return WINCODEC_ERR_UNSUPPORTEDOPERATION; + FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); + return E_NOTIMPL; } static HRESULT WINAPI PngDecoder_GetPreview(IWICBitmapDecoder *iface, @@ -1014,7 +1006,7 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface, IWICPalette *pIPalette) { PngDecoder *This = impl_from_IWICBitmapFrameDecode(iface); - png_uint_32 ret; + png_uint_32 ret, color_type, bit_depth; png_colorp png_palette; int num_palette; WICColor palette[256]; @@ -1028,30 +1020,58 @@ static HRESULT WINAPI PngDecoder_Frame_CopyPalette(IWICBitmapFrameDecode *iface, EnterCriticalSection(&This->lock); - ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette); - if (!ret) - { - hr = WINCODEC_ERR_PALETTEUNAVAILABLE; - goto end; - } + color_type = ppng_get_color_type(This->png_ptr, This->info_ptr); + bit_depth = ppng_get_bit_depth(This->png_ptr, This->info_ptr); - if (num_palette > 256) + if (color_type == PNG_COLOR_TYPE_PALETTE) { - ERR("palette has %i colors?!\n", num_palette); - hr = E_FAIL; - goto end; + ret = ppng_get_PLTE(This->png_ptr, This->info_ptr, &png_palette, &num_palette); + if (!ret) + { + hr = WINCODEC_ERR_PALETTEUNAVAILABLE; + goto end; + } + + if (num_palette > 256) + { + ERR("palette has %i colors?!\n", num_palette); + hr = E_FAIL; + goto end; + } + + ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values); + if (!ret) num_trans = 0; + + for (i=0; i<num_palette; i++) + { + BYTE alpha = (i < num_trans) ? trans_alpha[i] : 0xff; + palette[i] = (alpha << 24 | + png_palette[i].red << 16| + png_palette[i].green << 8| + png_palette[i].blue); + } } + else if (color_type == PNG_COLOR_TYPE_GRAY) { + ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values); - ret = ppng_get_tRNS(This->png_ptr, This->info_ptr, &trans_alpha, &num_trans, &trans_values); - if (!ret) num_trans = 0; + if (!ret) + { + hr = WINCODEC_ERR_PALETTEUNAVAILABLE; + goto end; + } - for (i=0; i<num_palette; i++) + num_palette = 1 << bit_depth; + + for (i=0; i<num_palette; i++) + { + BYTE alpha = (i == trans_values[0].gray) ? 0 : 0xff; + BYTE val = i * 255 / (num_palette - 1); + palette[i] = (alpha << 24 | val << 16 | val << 8 | val); + } + } + else { - BYTE alpha = (i < num_trans) ? trans_alpha[i] : 0xff; - palette[i] = (alpha << 24 | - png_palette[i].red << 16| - png_palette[i].green << 8| - png_palette[i].blue); + hr = WINCODEC_ERR_PALETTEUNAVAILABLE; } end: @@ -1632,31 +1652,22 @@ static HRESULT WINAPI PngFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, /* Newer libpng versions don't accept larger palettes than the declared * bit depth, so we need to generate the palette of the correct length. */ - colors = 1 << This->format->bit_depth; + colors = min(This->colors, 1 << This->format->bit_depth); for (i = 0; i < colors; i++) { - if (i < This->colors) - { - png_palette[i].red = (This->palette[i] >> 16) & 0xff; - png_palette[i].green = (This->palette[i] >> 8) & 0xff; - png_palette[i].blue = This->palette[i] & 0xff; - trans[i] = (This->palette[i] >> 24) & 0xff; - if (trans[i] != 0xff) - num_trans++; - } - else - { - png_palette[i].red = 0; - png_palette[i].green = 0; - png_palette[i].blue = 0; - } + png_palette[i].red = (This->palette[i] >> 16) & 0xff; + png_palette[i].green = (This->palette[i] >> 8) & 0xff; + png_palette[i].blue = This->palette[i] & 0xff; + trans[i] = (This->palette[i] >> 24) & 0xff; + if (trans[i] != 0xff) + num_trans = i+1; } ppng_set_PLTE(This->png_ptr, This->info_ptr, png_palette, colors); if (num_trans) - ppng_set_tRNS(This->png_ptr, This->info_ptr, trans, colors, NULL); + ppng_set_tRNS(This->png_ptr, This->info_ptr, trans, num_trans, NULL); } ppng_write_info(This->png_ptr, This->info_ptr); @@ -1958,22 +1969,11 @@ static HRESULT WINAPI PngEncoder_GetContainerFormat(IWICBitmapEncoder *iface, return E_NOTIMPL; } -static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info) +static HRESULT WINAPI PngEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, + IWICBitmapEncoderInfo **ppIEncoderInfo) { - IWICComponentInfo *comp_info; - HRESULT hr; - - TRACE("%p,%p\n", iface, info); - - if (!info) return E_INVALIDARG; - - hr = CreateComponentInfo(&CLSID_WICPngEncoder, &comp_info); - if (hr == S_OK) - { - hr = IWICComponentInfo_QueryInterface(comp_info, &IID_IWICBitmapEncoderInfo, (void **)info); - IWICComponentInfo_Release(comp_info); - } - return hr; + FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo); + return E_NOTIMPL; } static HRESULT WINAPI PngEncoder_SetColorContexts(IWICBitmapEncoder *iface, diff --git a/dll/win32/windowscodecs/regsvr.c b/dll/win32/windowscodecs/regsvr.c index aba6c0a0ee..756fb19651 100644 --- a/dll/win32/windowscodecs/regsvr.c +++ b/dll/win32/windowscodecs/regsvr.c @@ -1194,10 +1194,6 @@ static GUID const * const tiff_decode_formats[] = { &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat8bppGray, - &GUID_WICPixelFormat16bppGray, - &GUID_WICPixelFormat32bppGrayFloat, - &GUID_WICPixelFormat1bppIndexed, - &GUID_WICPixelFormat2bppIndexed, &GUID_WICPixelFormat4bppIndexed, &GUID_WICPixelFormat8bppIndexed, &GUID_WICPixelFormat24bppBGR, @@ -1207,9 +1203,6 @@ static GUID const * const tiff_decode_formats[] = { &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat64bppRGBA, &GUID_WICPixelFormat64bppPRGBA, - &GUID_WICPixelFormat32bppCMYK, - &GUID_WICPixelFormat64bppCMYK, - &GUID_WICPixelFormat128bppRGBAFloat, NULL }; @@ -1335,11 +1328,6 @@ static GUID const * const bmp_encode_formats[] = { &GUID_WICPixelFormat16bppBGR565, &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat32bppBGR, - &GUID_WICPixelFormatBlackWhite, - &GUID_WICPixelFormat1bppIndexed, - &GUID_WICPixelFormat2bppIndexed, - &GUID_WICPixelFormat4bppIndexed, - &GUID_WICPixelFormat8bppIndexed, NULL }; @@ -1365,10 +1353,6 @@ static GUID const * const tiff_encode_formats[] = { &GUID_WICPixelFormatBlackWhite, &GUID_WICPixelFormat4bppGray, &GUID_WICPixelFormat8bppGray, - &GUID_WICPixelFormat1bppIndexed, - &GUID_WICPixelFormat2bppIndexed, - &GUID_WICPixelFormat4bppIndexed, - &GUID_WICPixelFormat8bppIndexed, &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat32bppBGRA, &GUID_WICPixelFormat32bppPBGRA, @@ -1394,16 +1378,6 @@ static struct regsvr_encoder const encoder_list[] = { ".bmp,.dib,.rle", bmp_encode_formats }, - { &CLSID_WICGifEncoder, - "The Wine Project", - "GIF Encoder", - "1.0.0.0", - &GUID_VendorMicrosoft, - &GUID_ContainerFormatGif, - "image/gif", - ".gif", - gif_formats - }, { &CLSID_WICJpegEncoder, "The Wine Project", "JPEG Encoder", @@ -1463,11 +1437,8 @@ static GUID const * const converter_formats[] = { &GUID_WICPixelFormat24bppBGR, &GUID_WICPixelFormat24bppRGB, &GUID_WICPixelFormat32bppBGR, - &GUID_WICPixelFormat32bppRGB, &GUID_WICPixelFormat32bppBGRA, - &GUID_WICPixelFormat32bppRGBA, &GUID_WICPixelFormat32bppPBGRA, - &GUID_WICPixelFormat32bppPRGBA, &GUID_WICPixelFormat32bppGrayFloat, &GUID_WICPixelFormat48bppRGB, &GUID_WICPixelFormat64bppRGBA, @@ -1739,13 +1710,6 @@ static BYTE const channel_mask_16bit2[] = { 0x00, 0x00, 0xff, 0xff, 0x00, 0x00, static BYTE const channel_mask_16bit3[] = { 0x00, 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0x00 }; static BYTE const channel_mask_16bit4[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff }; -static BYTE const channel_mask_32bit[] = { 0xff, 0xff, 0xff, 0xff, 0x00, 0x00, 0x00, 0x00 }; - -static BYTE const channel_mask_128bit1[] = { 0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; -static BYTE const channel_mask_128bit2[] = { 0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00 }; -static BYTE const channel_mask_128bit3[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff,0x00,0x00,0x00,0x00 }; -static BYTE const channel_mask_128bit4[] = { 0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0xff,0xff,0xff,0xff }; - static BYTE const channel_mask_5bit[] = { 0x1f, 0x00 }; static BYTE const channel_mask_5bit2[] = { 0xe0, 0x03 }; static BYTE const channel_mask_5bit3[] = { 0x00, 0x7c }; @@ -1762,9 +1726,6 @@ static BYTE const * const channel_masks_8bit[] = { channel_mask_8bit, static BYTE const * const channel_masks_16bit[] = { channel_mask_16bit, channel_mask_16bit2, channel_mask_16bit3, channel_mask_16bit4}; -static BYTE const * const channel_masks_32bit[] = { channel_mask_32bit }; -static BYTE const * const channel_masks_128bit[] = { channel_mask_128bit1, channel_mask_128bit2, channel_mask_128bit3, channel_mask_128bit4 }; - static BYTE const * const channel_masks_BGRA5551[] = { channel_mask_5bit, channel_mask_5bit2, channel_mask_5bit3, channel_mask_5bit4 }; @@ -1781,7 +1742,7 @@ static struct regsvr_pixelformat const pixelformat_list[] = { 1, /* channel count */ channel_masks_1bit, WICPixelFormatNumericRepresentationIndexed, - 0 + 1 }, { &GUID_WICPixelFormat2bppIndexed, "The Wine Project", @@ -1792,7 +1753,7 @@ static struct regsvr_pixelformat const pixelformat_list[] = { 1, /* channel count */ channel_masks_2bit, WICPixelFormatNumericRepresentationIndexed, - 0 + 1 }, { &GUID_WICPixelFormat4bppIndexed, "The Wine Project", @@ -1803,7 +1764,7 @@ static struct regsvr_pixelformat const pixelformat_list[] = { 1, /* channel count */ channel_masks_4bit, WICPixelFormatNumericRepresentationIndexed, - 0 + 1 }, { &GUID_WICPixelFormat8bppIndexed, "The Wine Project", @@ -1814,7 +1775,7 @@ static struct regsvr_pixelformat const pixelformat_list[] = { 1, /* channel count */ channel_masks_8bit, WICPixelFormatNumericRepresentationIndexed, - 0 + 1 }, { &GUID_WICPixelFormatBlackWhite, "The Wine Project", @@ -1937,17 +1898,6 @@ static struct regsvr_pixelformat const pixelformat_list[] = { WICPixelFormatNumericRepresentationUnsignedInteger, 0 }, - { &GUID_WICPixelFormat32bppRGB, - "The Wine Project", - "32bpp RGB", - NULL, /* no version */ - &GUID_VendorMicrosoft, - 32, /* bitsperpixel */ - 3, /* channel count */ - channel_masks_8bit, - WICPixelFormatNumericRepresentationUnsignedInteger, - 0 - }, { &GUID_WICPixelFormat32bppBGRA, "The Wine Project", "32bpp BGRA", @@ -1959,17 +1909,6 @@ static struct regsvr_pixelformat const pixelformat_list[] = { WICPixelFormatNumericRepresentationUnsignedInteger, 1 }, - { &GUID_WICPixelFormat32bppRGBA, - "The Wine Project", - "32bpp RGBA", - NULL, /* no version */ - &GUID_VendorMicrosoft, - 32, /* bitsperpixel */ - 4, /* channel count */ - channel_masks_8bit, - WICPixelFormatNumericRepresentationUnsignedInteger, - 1 - }, { &GUID_WICPixelFormat32bppPBGRA, "The Wine Project", "32bpp PBGRA", @@ -1981,28 +1920,6 @@ static struct regsvr_pixelformat const pixelformat_list[] = { WICPixelFormatNumericRepresentationUnsignedInteger, 1 }, - { &GUID_WICPixelFormat32bppPRGBA, - "The Wine Project", - "32bpp PRGBA", - NULL, /* no version */ - &GUID_VendorMicrosoft, - 32, /* bitsperpixel */ - 4, /* channel count */ - channel_masks_8bit, - WICPixelFormatNumericRepresentationUnsignedInteger, - 1 - }, - { &GUID_WICPixelFormat32bppGrayFloat, - "The Wine Project", - "32bpp GrayFloat", - NULL, /* no version */ - &GUID_VendorMicrosoft, - 32, /* bitsperpixel */ - 1, /* channel count */ - channel_masks_32bit, - WICPixelFormatNumericRepresentationFloat, - 0 - }, { &GUID_WICPixelFormat48bppRGB, "The Wine Project", "48bpp RGB", @@ -2047,28 +1964,6 @@ static struct regsvr_pixelformat const pixelformat_list[] = { WICPixelFormatNumericRepresentationUnsignedInteger, 0 }, - { &GUID_WICPixelFormat64bppCMYK, - "The Wine Project", - "64bpp CMYK", - NULL, /* no version */ - &GUID_VendorMicrosoft, - 64, /* bitsperpixel */ - 4, /* channel count */ - channel_masks_16bit, - WICPixelFormatNumericRepresentationUnsignedInteger, - 0 - }, - { &GUID_WICPixelFormat128bppRGBAFloat, - "The Wine Project", - "128bpp RGBAFloat", - NULL, /* no version */ - &GUID_VendorMicrosoft, - 128, /* bitsperpixel */ - 4, /* channel count */ - channel_masks_128bit, - WICPixelFormatNumericRepresentationFloat, - 1 - }, { NULL } /* list terminator */ }; diff --git a/dll/win32/windowscodecs/scaler.c b/dll/win32/windowscodecs/scaler.c index a7c2447f53..8e267e314a 100644 --- a/dll/win32/windowscodecs/scaler.c +++ b/dll/win32/windowscodecs/scaler.c @@ -21,7 +21,6 @@ typedef struct BitmapScaler { IWICBitmapScaler IWICBitmapScaler_iface; LONG ref; - IMILBitmapScaler IMILBitmapScaler_iface; IWICBitmapSource *source; UINT width, height; UINT src_width, src_height; @@ -37,11 +36,6 @@ static inline BitmapScaler *impl_from_IWICBitmapScaler(IWICBitmapScaler *iface) return CONTAINING_RECORD(iface, BitmapScaler, IWICBitmapScaler_iface); } -static inline BitmapScaler *impl_from_IMILBitmapScaler(IMILBitmapScaler *iface) -{ - return CONTAINING_RECORD(iface, BitmapScaler, IMILBitmapScaler_iface); -} - static HRESULT WINAPI BitmapScaler_QueryInterface(IWICBitmapScaler *iface, REFIID iid, void **ppv) { @@ -56,13 +50,8 @@ static HRESULT WINAPI BitmapScaler_QueryInterface(IWICBitmapScaler *iface, REFII { *ppv = &This->IWICBitmapScaler_iface; } - else if (IsEqualIID(&IID_IMILBitmapScaler, iid)) - { - *ppv = &This->IMILBitmapScaler_iface; - } else { - FIXME("unknown interface %s\n", debugstr_guid(iid)); *ppv = NULL; return E_NOINTERFACE; } @@ -371,163 +360,6 @@ static const IWICBitmapScalerVtbl BitmapScaler_Vtbl = { BitmapScaler_Initialize }; -static HRESULT WINAPI IMILBitmapScaler_QueryInterface(IMILBitmapScaler *iface, REFIID iid, - void **ppv) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - - TRACE("(%p,%s,%p)\n", iface, debugstr_guid(iid), ppv); - - if (!ppv) return E_INVALIDARG; - - if (IsEqualIID(&IID_IUnknown, iid) || - IsEqualIID(&IID_IMILBitmapScaler, iid) || - IsEqualIID(&IID_IMILBitmapSource, iid)) - { - IUnknown_AddRef(&This->IMILBitmapScaler_iface); - *ppv = &This->IMILBitmapScaler_iface; - return S_OK; - } - else if (IsEqualIID(&IID_IWICBitmapScaler, iid) || - IsEqualIID(&IID_IWICBitmapSource, iid)) - { - IUnknown_AddRef(&This->IWICBitmapScaler_iface); - *ppv = &This->IWICBitmapScaler_iface; - return S_OK; - } - - FIXME("unknown interface %s\n", debugstr_guid(iid)); - *ppv = NULL; - return E_NOINTERFACE; -} - -static ULONG WINAPI IMILBitmapScaler_AddRef(IMILBitmapScaler *iface) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - return IWICBitmapScaler_AddRef(&This->IWICBitmapScaler_iface); -} - -static ULONG WINAPI IMILBitmapScaler_Release(IMILBitmapScaler *iface) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - return IWICBitmapScaler_Release(&This->IWICBitmapScaler_iface); -} - -static HRESULT WINAPI IMILBitmapScaler_GetSize(IMILBitmapScaler *iface, - UINT *width, UINT *height) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - - TRACE("(%p,%p,%p)\n", iface, width, height); - - if (!This->source) - return WINCODEC_ERR_NOTINITIALIZED; - - return IWICBitmapScaler_GetSize(&This->IWICBitmapScaler_iface, width, height); -} - -static HRESULT WINAPI IMILBitmapScaler_GetPixelFormat(IMILBitmapScaler *iface, - int *format) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - IMILBitmapSource *source; - HRESULT hr; - - TRACE("(%p,%p)\n", iface, format); - - if (!format) return E_INVALIDARG; - - if (!This->source) - return WINCODEC_ERR_NOTINITIALIZED; - - hr = IWICBitmapSource_QueryInterface(This->source, &IID_IMILBitmapSource, (void **)&source); - if (hr == S_OK) - { - hr = source->lpVtbl->GetPixelFormat(source, format); - source->lpVtbl->Release(source); - } - return hr; -} - -static HRESULT WINAPI IMILBitmapScaler_GetResolution(IMILBitmapScaler *iface, - double *dpix, double *dpiy) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - - TRACE("(%p,%p,%p)\n", iface, dpix, dpiy); - - if (!This->source) - return WINCODEC_ERR_NOTINITIALIZED; - - return IWICBitmapScaler_GetResolution(&This->IWICBitmapScaler_iface, dpix, dpiy); -} - -static HRESULT WINAPI IMILBitmapScaler_CopyPalette(IMILBitmapScaler *iface, - IWICPalette *palette) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - - TRACE("(%p,%p)\n", iface, palette); - - if (!This->source) - return WINCODEC_ERR_NOTINITIALIZED; - - return IWICBitmapScaler_CopyPalette(&This->IWICBitmapScaler_iface, palette); -} - -static HRESULT WINAPI IMILBitmapScaler_CopyPixels(IMILBitmapScaler *iface, - const WICRect *rc, UINT stride, UINT size, BYTE *buffer) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - - TRACE("(%p,%p,%u,%u,%p)\n", iface, rc, stride, size, buffer); - - if (!This->source) - return WINCODEC_ERR_NOTINITIALIZED; - - return IWICBitmapScaler_CopyPixels(&This->IWICBitmapScaler_iface, rc, stride, size, buffer); -} - -static HRESULT WINAPI IMILBitmapScaler_unknown1(IMILBitmapScaler *iface, void **ppv) -{ - TRACE("(%p,%p)\n", iface, ppv); - return E_NOINTERFACE; -} - -static HRESULT WINAPI IMILBitmapScaler_Initialize(IMILBitmapScaler *iface, - IMILBitmapSource *mil_source, UINT width, UINT height, - WICBitmapInterpolationMode mode) -{ - BitmapScaler *This = impl_from_IMILBitmapScaler(iface); - IWICBitmapSource *wic_source; - HRESULT hr; - - TRACE("(%p,%p,%u,%u,%u)\n", iface, mil_source, width, height, mode); - - if (!mil_source) return E_INVALIDARG; - - hr = mil_source->lpVtbl->QueryInterface(mil_source, &IID_IWICBitmapSource, (void **)&wic_source); - if (hr == S_OK) - { - hr = IWICBitmapScaler_Initialize(&This->IWICBitmapScaler_iface, wic_source, width, height, mode); - IWICBitmapSource_Release(wic_source); - } - return hr; -} - -static const IMILBitmapScalerVtbl IMILBitmapScaler_Vtbl = { - IMILBitmapScaler_QueryInterface, - IMILBitmapScaler_AddRef, - IMILBitmapScaler_Release, - IMILBitmapScaler_GetSize, - IMILBitmapScaler_GetPixelFormat, - IMILBitmapScaler_GetResolution, - IMILBitmapScaler_CopyPalette, - IMILBitmapScaler_CopyPixels, - IMILBitmapScaler_unknown1, - IMILBitmapScaler_Initialize -}; - HRESULT BitmapScaler_Create(IWICBitmapScaler **scaler) { BitmapScaler *This; @@ -536,7 +368,6 @@ HRESULT BitmapScaler_Create(IWICBitmapScaler **scaler) if (!This) return E_OUTOFMEMORY; This->IWICBitmapScaler_iface.lpVtbl = &BitmapScaler_Vtbl; - This->IMILBitmapScaler_iface.lpVtbl = &IMILBitmapScaler_Vtbl; This->ref = 1; This->source = NULL; This->width = 0; diff --git a/dll/win32/windowscodecs/tiffformat.c b/dll/win32/windowscodecs/tiffformat.c index 740de4955b..55423028a4 100644 --- a/dll/win32/windowscodecs/tiffformat.c +++ b/dll/win32/windowscodecs/tiffformat.c @@ -1,6 +1,5 @@ /* * 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 @@ -304,8 +303,6 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) } decode_info->planar = planar; - TRACE("planar %u, photometric %u, samples %u, bps %u\n", planar, photometric, samples, bps); - switch(photometric) { case 0: /* WhiteIsZero */ @@ -370,28 +367,14 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) } } break; - case 16: - if (samples != 1) - { - FIXME("unhandled 16bpp grayscale sample count %u\n", samples); - return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; - } - decode_info->format = &GUID_WICPixelFormat16bppGray; - break; - case 32: - if (samples != 1) - { - FIXME("unhandled 32bpp grayscale sample count %u\n", samples); - return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; - } - decode_info->format = &GUID_WICPixelFormat32bppGrayFloat; - break; default: - WARN("unhandled greyscale bit count %u\n", bps); - return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; + FIXME("unhandled greyscale bit count %u\n", bps); + return E_FAIL; } break; case 2: /* RGB */ + decode_info->bpp = bps * samples; + if (samples == 4) { ret = pTIFFGetField(tiff, TIFFTAG_EXTRASAMPLES, &extra_sample_count, &extra_samples); @@ -408,12 +391,8 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) return E_FAIL; } - decode_info->bpp = max(bps, 8) * samples; - decode_info->source_bpp = bps * samples; switch(bps) { - case 1: - case 4: case 8: decode_info->reverse_bgr = 1; if (samples == 3) @@ -451,17 +430,9 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) return E_FAIL; } break; - case 32: - if (samples != 4) - { - FIXME("unhandled 32bpp RGB sample count %u\n", samples); - return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; - } - decode_info->format = &GUID_WICPixelFormat128bppRGBAFloat; - break; default: - WARN("unhandled RGB bit count %u\n", bps); - return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; + FIXME("unhandled RGB bit count %u\n", bps); + return E_FAIL; } break; case 3: /* RGB Palette */ @@ -475,12 +446,6 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) decode_info->bpp = bps; switch (bps) { - case 1: - decode_info->format = &GUID_WICPixelFormat1bppIndexed; - break; - case 2: - decode_info->format = &GUID_WICPixelFormat2bppIndexed; - break; case 4: decode_info->format = &GUID_WICPixelFormat4bppIndexed; break; @@ -492,31 +457,8 @@ static HRESULT tiff_get_decode_info(TIFF *tiff, tiff_decode_info *decode_info) return E_FAIL; } break; - - case 5: /* Separated */ - if (samples != 4) - { - FIXME("unhandled Separated sample count %u\n", samples); - return E_FAIL; - } - - decode_info->bpp = bps * samples; - switch(bps) - { - case 8: - decode_info->format = &GUID_WICPixelFormat32bppCMYK; - break; - case 16: - decode_info->format = &GUID_WICPixelFormat64bppCMYK; - break; - - default: - WARN("unhandled Separated bit count %u\n", bps); - return WINCODEC_ERR_UNSUPPORTEDPIXELFORMAT; - } - break; - case 4: /* Transparency mask */ + case 5: /* CMYK */ case 6: /* YCbCr */ case 8: /* CIELab */ default: @@ -667,7 +609,6 @@ static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream * { TiffDecoder *This = impl_from_IWICBitmapDecoder(iface); TIFF *tiff; - tiff_decode_info decode_info; HRESULT hr=S_OK; TRACE("(%p,%p,%x)\n", iface, pIStream, cacheOptions); @@ -681,20 +622,13 @@ static HRESULT WINAPI TiffDecoder_Initialize(IWICBitmapDecoder *iface, IStream * } tiff = tiff_open_stream(pIStream, "r"); + if (!tiff) { hr = E_FAIL; goto exit; } - /* make sure that TIFF format is supported */ - hr = tiff_get_decode_info(tiff, &decode_info); - if (hr != S_OK) - { - pTIFFClose(tiff); - goto exit; - } - This->tiff = tiff; This->stream = pIStream; IStream_AddRef(pIStream); @@ -743,12 +677,8 @@ static HRESULT WINAPI TiffDecoder_CopyPalette(IWICBitmapDecoder *iface, static HRESULT WINAPI TiffDecoder_GetMetadataQueryReader(IWICBitmapDecoder *iface, IWICMetadataQueryReader **ppIMetadataQueryReader) { - TRACE("(%p,%p)\n", iface, ppIMetadataQueryReader); - - if (!ppIMetadataQueryReader) return E_INVALIDARG; - - *ppIMetadataQueryReader = NULL; - return WINCODEC_ERR_UNSUPPORTEDOPERATION; + FIXME("(%p,%p): stub\n", iface, ppIMetadataQueryReader); + return E_NOTIMPL; } static HRESULT WINAPI TiffDecoder_GetPreview(IWICBitmapDecoder *iface, @@ -1010,183 +940,34 @@ static HRESULT WINAPI TiffFrameDecode_CopyPalette(IWICBitmapFrameDecode *iface, static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT tile_y) { + HRESULT hr=S_OK; tsize_t ret; int swap_bytes; swap_bytes = pTIFFIsByteSwapped(This->parent->tiff); ret = pTIFFSetDirectory(This->parent->tiff, This->index); - if (ret == -1) - return E_FAIL; - - if (This->decode_info.tiled) - ret = pTIFFReadEncodedTile(This->parent->tiff, tile_x + tile_y * This->decode_info.tiles_across, This->cached_tile, This->decode_info.tile_size); - else - ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size); if (ret == -1) - return E_FAIL; + hr = E_FAIL; - /* 3bpp RGB */ - if (This->decode_info.source_bpp == 3 && This->decode_info.samples == 3 && This->decode_info.bpp == 24) + if (hr == S_OK) { - BYTE *srcdata, *src, *dst; - DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 3 + 7) / 8; - - count = width_bytes * This->decode_info.tile_height; - - srcdata = HeapAlloc(GetProcessHeap(), 0, count); - if (!srcdata) return E_OUTOFMEMORY; - memcpy(srcdata, This->cached_tile, count); - - for (y = 0; y < This->decode_info.tile_height; y++) + if (This->decode_info.tiled) { - src = srcdata + y * width_bytes; - dst = This->cached_tile + y * This->decode_info.tile_width * 3; - - for (x = 0; x < This->decode_info.tile_width; x += 8) - { - dst[2] = (src[0] & 0x80) ? 0xff : 0; /* R */ - dst[1] = (src[0] & 0x40) ? 0xff : 0; /* G */ - dst[0] = (src[0] & 0x20) ? 0xff : 0; /* B */ - if (x + 1 < This->decode_info.tile_width) - { - dst[5] = (src[0] & 0x10) ? 0xff : 0; /* R */ - dst[4] = (src[0] & 0x08) ? 0xff : 0; /* G */ - dst[3] = (src[0] & 0x04) ? 0xff : 0; /* B */ - } - if (x + 2 < This->decode_info.tile_width) - { - dst[8] = (src[0] & 0x02) ? 0xff : 0; /* R */ - dst[7] = (src[0] & 0x01) ? 0xff : 0; /* G */ - dst[6] = (src[1] & 0x80) ? 0xff : 0; /* B */ - } - if (x + 3 < This->decode_info.tile_width) - { - dst[11] = (src[1] & 0x40) ? 0xff : 0; /* R */ - dst[10] = (src[1] & 0x20) ? 0xff : 0; /* G */ - dst[9] = (src[1] & 0x10) ? 0xff : 0; /* B */ - } - if (x + 4 < This->decode_info.tile_width) - { - dst[14] = (src[1] & 0x08) ? 0xff : 0; /* R */ - dst[13] = (src[1] & 0x04) ? 0xff : 0; /* G */ - dst[12] = (src[1] & 0x02) ? 0xff : 0; /* B */ - } - if (x + 5 < This->decode_info.tile_width) - { - dst[17] = (src[1] & 0x01) ? 0xff : 0; /* R */ - dst[16] = (src[2] & 0x80) ? 0xff : 0; /* G */ - dst[15] = (src[2] & 0x40) ? 0xff : 0; /* B */ - } - if (x + 6 < This->decode_info.tile_width) - { - dst[20] = (src[2] & 0x20) ? 0xff : 0; /* R */ - dst[19] = (src[2] & 0x10) ? 0xff : 0; /* G */ - dst[18] = (src[2] & 0x08) ? 0xff : 0; /* B */ - } - if (x + 7 < This->decode_info.tile_width) - { - dst[23] = (src[2] & 0x04) ? 0xff : 0; /* R */ - dst[22] = (src[2] & 0x02) ? 0xff : 0; /* G */ - dst[21] = (src[2] & 0x01) ? 0xff : 0; /* B */ - } - src += 3; - dst += 24; - } + ret = pTIFFReadEncodedTile(This->parent->tiff, tile_x + tile_y * This->decode_info.tiles_across, This->cached_tile, This->decode_info.tile_size); } - - HeapFree(GetProcessHeap(), 0, srcdata); - } - /* 12bpp RGB */ - else if (This->decode_info.source_bpp == 12 && This->decode_info.samples == 3 && This->decode_info.bpp == 24) - { - BYTE *srcdata, *src, *dst; - DWORD x, y, count, width_bytes = (This->decode_info.tile_width * 12 + 7) / 8; - - count = width_bytes * This->decode_info.tile_height; - - srcdata = HeapAlloc(GetProcessHeap(), 0, count); - if (!srcdata) return E_OUTOFMEMORY; - memcpy(srcdata, This->cached_tile, count); - - for (y = 0; y < This->decode_info.tile_height; y++) + else { - src = srcdata + y * width_bytes; - dst = This->cached_tile + y * This->decode_info.tile_width * 3; - - for (x = 0; x < This->decode_info.tile_width; x += 2) - { - dst[0] = ((src[1] & 0xf0) >> 4) * 17; /* B */ - dst[1] = (src[0] & 0x0f) * 17; /* G */ - dst[2] = ((src[0] & 0xf0) >> 4) * 17; /* R */ - if (x + 1 < This->decode_info.tile_width) - { - dst[5] = (src[1] & 0x0f) * 17; /* B */ - dst[4] = ((src[2] & 0xf0) >> 4) * 17; /* G */ - dst[3] = (src[2] & 0x0f) * 17; /* R */ - } - src += 3; - dst += 6; - } + ret = pTIFFReadEncodedStrip(This->parent->tiff, tile_y, This->cached_tile, This->decode_info.tile_size); } - HeapFree(GetProcessHeap(), 0, srcdata); - } - /* 4bpp RGBA */ - else if (This->decode_info.source_bpp == 4 && This->decode_info.samples == 4 && This->decode_info.bpp == 32) - { - BYTE *src, *dst; - DWORD count; - - /* 1 source byte expands to 2 BGRA samples */ - count = (This->decode_info.tile_width * This->decode_info.tile_height + 1) / 2; - - src = This->cached_tile + count - 1; - dst = This->cached_tile + This->decode_info.tile_size; - - while (count--) - { - BYTE b = *src--; - - dst -= 8; - dst[2] = (b & 0x80) ? 0xff : 0; /* R */ - dst[1] = (b & 0x40) ? 0xff : 0; /* G */ - dst[0] = (b & 0x20) ? 0xff : 0; /* B */ - dst[3] = (b & 0x10) ? 0xff : 0; /* A */ - dst[6] = (b & 0x08) ? 0xff : 0; /* R */ - dst[5] = (b & 0x04) ? 0xff : 0; /* G */ - dst[4] = (b & 0x02) ? 0xff : 0; /* B */ - dst[7] = (b & 0x01) ? 0xff : 0; /* A */ - } + if (ret == -1) + hr = E_FAIL; } - /* 16bpp RGBA */ - else if (This->decode_info.source_bpp == 16 && This->decode_info.samples == 4 && This->decode_info.bpp == 32) - { - BYTE *src, *dst; - DWORD count = This->decode_info.tile_width * This->decode_info.tile_height; - src = This->cached_tile + count * 2; - dst = This->cached_tile + This->decode_info.tile_size; - - while (count--) - { - BYTE b[2]; - - src -= 2; - dst -= 4; - - b[0] = src[0]; - b[1] = src[1]; - - dst[0] = ((b[1] & 0xf0) >> 4) * 17; /* B */ - dst[1] = (b[0] & 0x0f) * 17; /* G */ - dst[2] = ((b[0] & 0xf0) >> 4) * 17; /* R */ - dst[3] = (b[1] & 0x0f) * 17; /* A */ - } - } /* 8bpp grayscale with extra alpha */ - else if (This->decode_info.source_bpp == 16 && This->decode_info.samples == 2 && This->decode_info.bpp == 32) + if (hr == S_OK && This->decode_info.source_bpp == 16 && This->decode_info.samples == 2 && This->decode_info.bpp == 32) { BYTE *src; DWORD *dst, count = This->decode_info.tile_width * This->decode_info.tile_height; @@ -1201,7 +982,7 @@ static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT } } - if (This->decode_info.reverse_bgr) + if (hr == S_OK && This->decode_info.reverse_bgr) { if (This->decode_info.bps == 8) { @@ -1212,7 +993,7 @@ static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT } } - if (swap_bytes && This->decode_info.bps > 8) + if (hr == S_OK && swap_bytes && This->decode_info.bps > 8) { UINT row, i, samples_per_row; BYTE *sample, temp; @@ -1240,7 +1021,7 @@ static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT } } - if (This->decode_info.invert_grayscale) + if (hr == S_OK && This->decode_info.invert_grayscale) { BYTE *byte, *end; @@ -1256,10 +1037,13 @@ static HRESULT TiffFrameDecode_ReadTile(TiffFrameDecode *This, UINT tile_x, UINT *byte = ~(*byte); } - This->cached_tile_x = tile_x; - This->cached_tile_y = tile_y; + if (hr == S_OK) + { + This->cached_tile_x = tile_x; + This->cached_tile_y = tile_y; + } - return S_OK; + return hr; } static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, @@ -1296,7 +1080,7 @@ static HRESULT WINAPI TiffFrameDecode_CopyPixels(IWICBitmapFrameDecode *iface, if (cbStride < bytesperrow) return E_INVALIDARG; - if ((cbStride * (prc->Height-1)) + ((prc->Width * This->decode_info.bpp) + 7)/8 > cbBufferSize) + if ((cbStride * prc->Height) > cbBufferSize) return E_INVALIDARG; min_tile_x = prc->X / This->decode_info.tile_width; @@ -1610,10 +1394,6 @@ static const struct tiff_encode_format formats[] = { {&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_WICPixelFormat2bppIndexed, 3, 2, 1, 2, 0, 0, 0}, - {&GUID_WICPixelFormat4bppIndexed, 3, 4, 1, 4, 0, 0, 0}, - {&GUID_WICPixelFormat8bppIndexed, 3, 8, 1, 8, 0, 0, 0}, {0} }; @@ -1896,21 +1676,6 @@ static HRESULT WINAPI TiffFrameEncode_WritePixels(IWICBitmapFrameEncode *iface, 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; } @@ -2109,22 +1874,11 @@ static HRESULT WINAPI TiffEncoder_GetContainerFormat(IWICBitmapEncoder *iface, return S_OK; } -static HRESULT WINAPI TiffEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, IWICBitmapEncoderInfo **info) +static HRESULT WINAPI TiffEncoder_GetEncoderInfo(IWICBitmapEncoder *iface, + IWICBitmapEncoderInfo **ppIEncoderInfo) { - 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; + FIXME("(%p,%p): stub\n", iface, ppIEncoderInfo); + return E_NOTIMPL; } static HRESULT WINAPI TiffEncoder_SetColorContexts(IWICBitmapEncoder *iface, @@ -2184,7 +1938,7 @@ static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface, hr = E_FAIL; } - if (SUCCEEDED(hr) && ppIEncoderOptions) + if (SUCCEEDED(hr)) { PROPBAG2 opts[2]= {{0}}; opts[0].pstrName = (LPOLESTR)wszTiffCompressionMethod; @@ -2202,7 +1956,7 @@ static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface, VARIANT v; VariantInit(&v); V_VT(&v) = VT_UI1; - V_UI1(&v) = WICTiffCompressionDontCare; + V_UNION(&v, bVal) = WICTiffCompressionDontCare; hr = IPropertyBag2_Write(*ppIEncoderOptions, 1, opts, &v); VariantClear(&v); if (FAILED(hr)) @@ -2244,7 +1998,7 @@ static HRESULT WINAPI TiffEncoder_CreateNewFrame(IWICBitmapEncoder *iface, else hr = E_OUTOFMEMORY; - if (FAILED(hr) && ppIEncoderOptions) + if (FAILED(hr)) { IPropertyBag2_Release(*ppIEncoderOptions); *ppIEncoderOptions = NULL; diff --git a/dll/win32/windowscodecs/wincodecs_private.h b/dll/win32/windowscodecs/wincodecs_private.h index 96ee8fd069..99daf093ad 100644 --- a/dll/win32/windowscodecs/wincodecs_private.h +++ b/dll/win32/windowscodecs/wincodecs_private.h @@ -55,13 +55,7 @@ DEFINE_GUID(GUID_WineContainerFormatTga, 0x0c44fda1,0xa5c5,0x4298,0x96,0x85,0x47 DEFINE_GUID(GUID_VendorWine, 0xddf46da1,0x7dc1,0x404e,0x98,0xf2,0xef,0xa4,0x8d,0xfc,0x95,0x0a); -DEFINE_GUID(IID_IMILBitmap,0xb1784d3f,0x8115,0x4763,0x13,0xaa,0x32,0xed,0xdb,0x68,0x29,0x4a); DEFINE_GUID(IID_IMILBitmapSource,0x7543696a,0xbc8d,0x46b0,0x5f,0x81,0x8d,0x95,0x72,0x89,0x72,0xbe); -DEFINE_GUID(IID_IMILBitmapLock,0xa67b2b53,0x8fa1,0x4155,0x8f,0x64,0x0c,0x24,0x7a,0x8f,0x84,0xcd); -DEFINE_GUID(IID_IMILBitmapScaler,0xa767b0f0,0x1c8c,0x4aef,0x56,0x8f,0xad,0xf9,0x6d,0xcf,0xd5,0xcb); -DEFINE_GUID(IID_IMILFormatConverter,0x7e2a746f,0x25c5,0x4851,0xb3,0xaf,0x44,0x3b,0x79,0x63,0x9e,0xc0); -DEFINE_GUID(IID_IMILPalette,0xca8e206f,0xf22c,0x4af7,0x6f,0xba,0x7b,0xed,0x5e,0xb1,0xc9,0x2f); - #define INTERFACE IMILBitmapSource DECLARE_INTERFACE_(IMILBitmapSource,IUnknown) { @@ -69,58 +63,16 @@ DECLARE_INTERFACE_(IMILBitmapSource,IUnknown) STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IWICBitmapSource methods ***/ - STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE; - STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE; - STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; - STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; - STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; /*** IMILBitmapSource methods ***/ - STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE; - STDMETHOD_(HRESULT,Lock)(THIS_ const WICRect *,DWORD,IWICBitmapLock **) PURE; - STDMETHOD_(HRESULT,Unlock)(THIS_ IWICBitmapLock *) PURE; - STDMETHOD_(HRESULT,SetPalette)(THIS_ IWICPalette *) PURE; - STDMETHOD_(HRESULT,SetResolution)(THIS_ double,double) PURE; - STDMETHOD_(HRESULT,AddDirtyRect)(THIS_ const WICRect *) PURE; + STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *); + STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *); + STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *); + STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *); + STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *); + STDMETHOD_(HRESULT,UnknownMethod1)(THIS_ void **); }; #undef INTERFACE -#define INTERFACE IMILBitmapScaler -DECLARE_INTERFACE_(IMILBitmapScaler,IUnknown) -{ - /*** IUnknown methods ***/ - STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; - STDMETHOD_(ULONG,AddRef)(THIS) PURE; - STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** IWICBitmapSource methods ***/ - STDMETHOD_(HRESULT,GetSize)(THIS_ UINT *,UINT *) PURE; - STDMETHOD_(HRESULT,GetPixelFormat)(THIS_ int *) PURE; - STDMETHOD_(HRESULT,GetResolution)(THIS_ double *,double *) PURE; - STDMETHOD_(HRESULT,CopyPalette)(THIS_ IWICPalette *) PURE; - STDMETHOD_(HRESULT,CopyPixels)(THIS_ const WICRect *,UINT,UINT,BYTE *) PURE; - /*** IMILBitmapScaler methods ***/ - STDMETHOD_(HRESULT,unknown1)(THIS_ void **) PURE; - STDMETHOD_(HRESULT,Initialize)(THIS_ IMILBitmapSource *,UINT,UINT,WICBitmapInterpolationMode); -}; -#undef INTERFACE - -#ifdef __i386__ /* thiscall functions are i386-specific */ - -#define THISCALL(func) __thiscall_ ## func -#define DEFINE_THISCALL_WRAPPER(func,args) \ - extern typeof(func) THISCALL(func); \ - __ASM_STDCALL_FUNC(__thiscall_ ## func, args, \ - "popl %eax\n\t" \ - "pushl %ecx\n\t" \ - "pushl %eax\n\t" \ - "jmp " __ASM_NAME(#func) __ASM_STDCALL(args) ) -#else /* __i386__ */ - -#define THISCALL(func) func -#define DEFINE_THISCALL_WRAPPER(func,args) /* nothing */ - -#endif /* __i386__ */ - #define INTERFACE IMILUnknown1 DECLARE_INTERFACE_(IMILUnknown1,IUnknown) { @@ -128,19 +80,6 @@ DECLARE_INTERFACE_(IMILUnknown1,IUnknown) STDMETHOD_(HRESULT,QueryInterface)(THIS_ REFIID,void **) PURE; STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE; - /*** thiscall method ***/ - STDMETHOD_(void,unknown1)(THIS_ void*) PURE; - /*** stdcall ***/ - STDMETHOD_(HRESULT,unknown2)(THIS_ void*, void*) PURE; - /*** thiscall method ***/ - STDMETHOD_(HRESULT,unknown3)(THIS_ void*) PURE; - /*** stdcall ***/ - STDMETHOD_(HRESULT,unknown4)(THIS_ void*) PURE; - STDMETHOD_(HRESULT,unknown5)(THIS_ void*) PURE; - STDMETHOD_(HRESULT,unknown6)(THIS_ DWORD64) PURE; - STDMETHOD_(HRESULT,unknown7)(THIS_ void*) PURE; - /*** thiscall method ***/ - STDMETHOD_(HRESULT,unknown8)(THIS) PURE; }; #undef INTERFACE @@ -152,9 +91,7 @@ DECLARE_INTERFACE_(IMILUnknown2,IUnknown) STDMETHOD_(ULONG,AddRef)(THIS) PURE; STDMETHOD_(ULONG,Release)(THIS) PURE; /*** unknown methods ***/ - STDMETHOD_(HRESULT,unknown1)(THIS_ void *,void **) PURE; - STDMETHOD_(HRESULT,unknown2)(THIS_ void *,void *) PURE; - STDMETHOD_(HRESULT,unknown3)(THIS_ void *) PURE; + STDMETHOD_(HRESULT,UnknownMethod1)(THIS_ void *, void *) PURE; }; #undef INTERFACE @@ -169,7 +106,6 @@ extern HRESULT PngEncoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN extern HRESULT BmpEncoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN; extern HRESULT DibDecoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN; extern HRESULT GifDecoder_CreateInstance(REFIID riid, void** ppv) DECLSPEC_HIDDEN; -extern HRESULT GifEncoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN; extern HRESULT IcoDecoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN; extern HRESULT JpegDecoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN; extern HRESULT JpegEncoder_CreateInstance(REFIID iid, void** ppv) DECLSPEC_HIDDEN; diff --git a/dll/win32/windowscodecs/windowscodecs.spec b/dll/win32/windowscodecs/windowscodecs.spec index 424b3075ce..8fd2470f11 100644 --- a/dll/win32/windowscodecs/windowscodecs.spec +++ b/dll/win32/windowscodecs/windowscodecs.spec @@ -105,8 +105,7 @@ @ stdcall IWICStream_InitializeFromIStream_Proxy(ptr ptr) IWICStream_InitializeFromIStream_Proxy_W @ stdcall IWICStream_InitializeFromMemory_Proxy(ptr ptr long) IWICStream_InitializeFromMemory_Proxy_W @ stdcall WICConvertBitmapSource(ptr ptr ptr) -@ stdcall WICCreateBitmapFromSection(long long ptr long long long ptr) -@ stdcall WICCreateBitmapFromSectionEx(long long ptr long long long long ptr) +@ stdcall -stub WICCreateBitmapFromSection(long long ptr long long long ptr) @ stdcall WICCreateColorContext_Proxy(ptr ptr) @ stdcall WICCreateImagingFactory_Proxy(long ptr) @ stub WICGetMetadataContentSize diff --git a/dll/win32/windowscodecs/windowscodecs_wincodec.idl b/dll/win32/windowscodecs/windowscodecs_wincodec.idl index fec63d04e1..33c0d4a580 100644 --- a/dll/win32/windowscodecs/windowscodecs_wincodec.idl +++ b/dll/win32/windowscodecs/windowscodecs_wincodec.idl @@ -76,13 +76,6 @@ coclass WICBmpEncoder { interface IWICBitmapEncoder; } ] coclass WICGifDecoder { interface IWICBitmapDecoder; } -[ - helpstring("WIC GIF Encoder"), - threading(both), - uuid(114f5598-0b22-40a0-86a1-c83ea495adbd) -] -coclass WICGifEncoder { interface IWICBitmapEncoder; } - [ helpstring("WIC ICO Decoder"), threading(both), diff --git a/media/doc/README.WINE b/media/doc/README.WINE index b94e76dc58..d1c733260d 100644 --- a/media/doc/README.WINE +++ b/media/doc/README.WINE @@ -196,7 +196,7 @@ reactos/dll/win32/version # Synced to Wine-3.0 reactos/dll/win32/vssapi # Synced to WineStaging-2.9 reactos/dll/win32/wbemdisp # Synced to Wine-3.0 reactos/dll/win32/wbemprox # Synced to Wine-3.0 -reactos/dll/win32/windowscodecs # Synced to WineStaging-2.16 +reactos/dll/win32/windowscodecs # Synced to Wine-3.0 reactos/dll/win32/windowscodecsext # Synced to WineStaging-2.9 reactos/dll/win32/winemp3.acm # Synced to WineStaging-2.16 reactos/dll/win32/wing32 # Synced to WineStaging-2.9
6 years, 11 months
1
0
0
0
← Newer
1
...
16
17
18
19
20
21
22
...
38
Older →
Jump to page:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
Results per page:
10
25
50
100
200