Wine-devel
Threads by month
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
November 2018
- 75 participants
- 771 discussions
[PATCH v2 3/3] comctl32/status: Checking size grip bounds inclusively.
by Waritnan Sookbuntherng 11 Nov '18
by Waritnan Sookbuntherng 11 Nov '18
11 Nov '18
Signed-off-by: Waritnan Sookbuntherng <lion328(a)hotmail.co.th>
---
dlls/comctl32/status.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/dlls/comctl32/status.c b/dlls/comctl32/status.c
index 3bf72fa577..ad69c54ba8 100644
--- a/dlls/comctl32/status.c
+++ b/dlls/comctl32/status.c
@@ -1011,6 +1011,9 @@ STATUSBAR_WMNCHitTest (const STATUS_INFO *infoPtr, INT x, INT y)
rect.left = rect.right - 13;
rect.top += 2;
+ /* checking POINT in RECT inclusively */
+ rect.right += 1;
+ rect.bottom += 1;
if (PtInRect (&rect, pt))
{
--
2.19.1
1
0
[PATCH] mlang: Add basic implementation for IMultiLanguage3_DetectInputCodepage
by Fabian Maurer 11 Nov '18
by Fabian Maurer 11 Nov '18
11 Nov '18
This is a first basic implementation that can handle
UTF-16/UTF-8 and should cover most text files.
It's currently not used by any known program,
but I intend to use the function for find.exe to detect encodings.
Signed-off-by: Fabian Maurer <dark.shadow4(a)web.de>
---
dlls/mlang/mlang.c | 35 +++++++++++-
dlls/mlang/tests/mlang.c | 114 +++++++++++++++++++++++++++++++++++++++
include/mlang.idl | 12 ++++-
3 files changed, 158 insertions(+), 3 deletions(-)
diff --git a/dlls/mlang/mlang.c b/dlls/mlang/mlang.c
index f12df298f1..e33c982c76 100644
--- a/dlls/mlang/mlang.c
+++ b/dlls/mlang/mlang.c
@@ -3097,8 +3097,39 @@ static HRESULT WINAPI fnIMultiLanguage3_DetectInputCodepage(
DetectEncodingInfo* lpEncoding,
INT* pnScores)
{
- FIXME("\n");
- return E_NOTIMPL;
+ INT test;
+
+ FIXME("(%u %u, %p, %p, %p, %p - semi-stub!\n", dwFlag, dwPrefWinCodePage, pSrcStr, pcSrcSize, lpEncoding, pnScores);
+
+ if (!pSrcStr || !lpEncoding || *pcSrcSize <= 0 || *pnScores <= 0)
+ return E_INVALIDARG;
+
+ test = IS_TEXT_UNICODE_SIGNATURE | IS_TEXT_UNICODE_REVERSE_SIGNATURE;
+ IsTextUnicode(pSrcStr, *pcSrcSize, &test);
+
+ if (test & IS_TEXT_UNICODE_SIGNATURE)
+ {
+ *pnScores = 1;
+ lpEncoding[0].nCodePage = 1200;
+ return S_OK;
+ }
+
+ if (test & IS_TEXT_UNICODE_REVERSE_SIGNATURE)
+ {
+ *pnScores = 1;
+ lpEncoding[0].nCodePage = 1201;
+ return S_OK;
+ }
+
+ /* Check for valid UTF-8 */
+ if (MultiByteToWideChar(CP_UTF8, MB_ERR_INVALID_CHARS, pSrcStr, *pcSrcSize, NULL, 0) > 0)
+ {
+ *pnScores = 1;
+ lpEncoding[0].nCodePage = 65001;
+ return S_OK;
+ }
+
+ return S_FALSE;
}
static HRESULT WINAPI fnIMultiLanguage3_ValidateCodePage(
diff --git a/dlls/mlang/tests/mlang.c b/dlls/mlang/tests/mlang.c
index b5d6fc6114..f57a870d93 100644
--- a/dlls/mlang/tests/mlang.c
+++ b/dlls/mlang/tests/mlang.c
@@ -2695,6 +2695,119 @@ static void test_MapFont(IMLangFontLink *font_link, IMLangFontLink2 *font_link2)
ReleaseDC(NULL, hdc);
}
+static void test_DetectInputCodepage(IMultiLanguage2 *ml2)
+{
+ static char str_empty[] = {0};
+ static char str_utf8_bom1[] = "\xef\xbb\xbf this is a test string with utf8 bom";
+ static char str_utf8_bom2[] = "\xef\xbb\xbf this is a test string with utf8 bom this is a test string with utf8 bom this is a test string with utf8 bom"
+ "this is a test string with utf8 bom this is a test string with utf8 bom this is a test string with utf8 bom this is a test string with utf8 bom";
+ static char str_shift_jis[] = {0x82, 0xB1, 0x82, 0xEA, 0x82, 0xCD, 0x93, 0xFA, 0x96, 0x7B, 0x8C, 0xEA, 0x82, 0xCC, 0x83, 0x65, 0x83, 0x4C, 0x83, 0x58, 0x83, 0x67, 0x82, 0xC5, 0x82, 0xB7, 0x00 };
+ static char str_utf16_be_with_bom[] = {
+ 0xFE, 0xFF, 0x00, 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73,
+ 0x00, 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6E,
+ 0x00, 0x20, 0x00, 0x55, 0x00, 0x54, 0x00, 0x46, 0x00, 0x31, 0x00, 0x36, 0x00 };
+ char *str_utf16_be_without_bom = &str_utf16_be_with_bom[2];
+ static char str_utf16_le_with_bom[] = {
+ 0xFF, 0xFE, 0x54, 0x00, 0x68, 0x00, 0x69, 0x00, 0x73, 0x00, 0x20, 0x00, 0x69, 0x00, 0x73, 0x00,
+ 0x20, 0x00, 0x74, 0x00, 0x65, 0x00, 0x78, 0x00, 0x74, 0x00, 0x20, 0x00, 0x69, 0x00, 0x6E, 0x00,
+ 0x20, 0x00, 0x55, 0x00, 0x54, 0x00, 0x46, 0x00, 0x31, 0x00, 0x36, 0x00, 0x00 };
+ char *str_utf16_le_without_bom = &str_utf16_le_with_bom[2];
+ static char str_utf8_hello_without_bom[] = { /* Hello in english, russian and japanese */
+ 0x48, 0x65, 0x6C, 0x6C, 0x6F, 0x20, 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5,
+ 0xD1, 0x82, 0x20, 0xE4, 0xBB, 0x8A, 0xE6, 0x97, 0xA5, 0xE3, 0x81, 0xAF, 0x00 };
+
+ DetectEncodingInfo encoding_info[5];
+ HRESULT result;
+ INT str_size;
+ INT encoding_count;
+
+ /* Test error conditions */
+
+ str_size = sizeof(str_empty);
+ encoding_count = ARRAY_SIZE(encoding_info);
+ result = IMultiLanguage2_DetectInputCodepage(ml2, MLDETECTCP_NONE, 0, NULL, &str_size, encoding_info, &encoding_count);
+ ok(result == E_INVALIDARG, "Expected E_INVALIDARG, got %#x\n", result);
+ ok(5 == encoding_count, "Expected encoding_count to be %d, got %d\n", 5, encoding_count);
+
+ str_size = sizeof(str_empty);
+ encoding_count = ARRAY_SIZE(encoding_info);
+ result = IMultiLanguage2_DetectInputCodepage(ml2, MLDETECTCP_NONE, 0, str_empty, &str_size, NULL, &encoding_count);
+ ok(result == E_INVALIDARG, "Expected E_INVALIDARG, got %#x\n", result);
+ ok(5 == encoding_count, "Expected encoding_count to be %d, got %d\n", 5, encoding_count);
+
+ str_size = 0;
+ encoding_count = ARRAY_SIZE(encoding_info);
+ result = IMultiLanguage2_DetectInputCodepage(ml2, MLDETECTCP_NONE, 0, str_empty, &str_size, encoding_info, &encoding_count);
+ ok(result == E_INVALIDARG, "Expected E_INVALIDARG, got %#x\n", result);
+ ok(5 == encoding_count, "Expected encoding_count to be %d, got %d\n", 5, encoding_count);
+
+ str_size = sizeof(str_empty);
+ encoding_count = 0;
+ result = IMultiLanguage2_DetectInputCodepage(ml2, MLDETECTCP_NONE, 0, str_empty, &str_size, encoding_info, &encoding_count);
+ ok(result == E_INVALIDARG, "Expected E_INVALIDARG, got %#x\n", result);
+ ok(0 == encoding_count, "Expected encoding_count to be %d, got %d\n", 0, encoding_count);
+
+ /* Test strings */
+
+#define run_DetectInputCodepage(flags, codepage_default, str) \
+ str_size = sizeof(str); \
+ encoding_count = ARRAY_SIZE(encoding_info); \
+ memset(&encoding_info, 0, sizeof(encoding_info)); \
+ result = IMultiLanguage2_DetectInputCodepage(ml2, flags, codepage_default, str, &str_size, encoding_info, &encoding_count);
+
+
+ run_DetectInputCodepage(MLDETECTCP_NONE, 0, str_utf8_bom1);
+ todo_wine
+ ok(result == S_FALSE, "Expected %#x, got %#x\n", S_FALSE, result);
+ ok(1 == encoding_count, "Expected encoding_count to be %d, got %d\n", 1, encoding_count);
+ ok(encoding_info[0].nCodePage == 65001, "Expected code-page %d, got %d\n", 65001, encoding_info[0].nCodePage);
+
+ run_DetectInputCodepage(MLDETECTCP_NONE, 0, str_utf8_bom2);
+ ok(result == S_OK, "Expected %#x, got %#x\n", S_OK, result);
+ todo_wine
+ ok(2 == encoding_count, "Expected encoding_count to be %d, got %d\n", 2, encoding_count);
+ todo_wine
+ ok(encoding_info[0].nCodePage == 1252, "Expected code-page %d, got %d\n", 1252, encoding_info[0].nCodePage);
+ todo_wine
+ ok(encoding_info[1].nCodePage == 65001, "Expected code-page %d, got %d\n", 65001, encoding_info[1].nCodePage);
+
+ run_DetectInputCodepage(MLDETECTCP_NONE, 0, str_shift_jis);
+ todo_wine
+ ok(result == S_OK, "Expected %#x, got %#x\n", S_OK, result);
+ todo_wine
+ ok(1 == encoding_count, "Expected encoding_count to be %d, got %d\n", 1, encoding_count);
+ todo_wine
+ ok(encoding_info[0].nCodePage == 932, "Expected code-page %d, got %d\n", 932, encoding_info[0].nCodePage);
+
+ run_DetectInputCodepage(MLDETECTCP_NONE, 0, str_utf16_be_with_bom);
+ ok(result == S_OK, "Expected %#x, got %#x\n", S_OK, result);
+ ok(1 == encoding_count, "Expected encoding_count to be %d, got %d\n", 1, encoding_count);
+ ok(encoding_info[0].nCodePage == 1201, "Expected code-page %d, got %d\n", 1201, encoding_info[0].nCodePage);
+
+ run_DetectInputCodepage(MLDETECTCP_NONE, 0, str_utf16_le_with_bom);
+ ok(result == S_OK, "Expected %#x, got %#x\n", S_OK, result);
+ ok(1 == encoding_count, "Expected encoding_count to be %d, got %d\n", 1, encoding_count);
+ ok(encoding_info[0].nCodePage == 1200, "Expected code-page %d, got %d\n", 1200, encoding_info[0].nCodePage);
+
+ run_DetectInputCodepage(MLDETECTCP_NONE, 0, str_utf16_be_without_bom);
+ ok(result == S_OK, "Expected %#x, got %#x\n", S_OK, result);
+ ok(1 == encoding_count, "Expected encoding_count to be %d, got %d\n", 1, encoding_count);
+ todo_wine
+ ok(encoding_info[0].nCodePage == 20127, "Expected code-page %d, got %d\n", 20127, encoding_info[0].nCodePage);
+
+ run_DetectInputCodepage(MLDETECTCP_NONE, 0, str_utf16_le_without_bom);
+ ok(result == S_OK, "Expected %#x, got %#x\n", S_OK, result);
+ ok(1 == encoding_count, "Expected encoding_count to be %d, got %d\n", 1, encoding_count);
+ todo_wine
+ ok(encoding_info[0].nCodePage == 20127, "Expected code-page %d, got %d\n", 20127, encoding_info[0].nCodePage);
+
+ run_DetectInputCodepage(MLDETECTCP_NONE, 0, str_utf8_hello_without_bom);
+ todo_wine
+ ok(result == S_FALSE, "Expected %#x, got %#x\n", S_FALSE, result);
+ ok(1 == encoding_count, "Expected encoding_count to be %d, got %d\n", 1, encoding_count);
+ ok(encoding_info[0].nCodePage == 65001, "Expected code-page %d, got %d\n", 65001, encoding_info[0].nCodePage);
+}
+
START_TEST(mlang)
{
IMultiLanguage *iML = NULL;
@@ -2761,6 +2874,7 @@ START_TEST(mlang)
test_IMultiLanguage2_ConvertStringFromUnicode(iML2);
test_IsCodePageInstallable(iML2);
+ test_DetectInputCodepage(iML2);
IMultiLanguage2_Release(iML2);
diff --git a/include/mlang.idl b/include/mlang.idl
index 5867648b04..a23fdb85f4 100644
--- a/include/mlang.idl
+++ b/include/mlang.idl
@@ -25,6 +25,16 @@ interface IStream;
cpp_quote("#define CPIOD_PEEK 0x40000000")
cpp_quote("#define CPIOD_FORCE_PROMPT 0x80000000")
+typedef enum tagMLDETECTCP
+{
+ MLDETECTCP_NONE = 0,
+ MLDETECTCP_7BIT = 1,
+ MLDETECTCP_8BIT = 2,
+ MLDETECTCP_DBCS = 4,
+ MLDETECTCP_HTML = 8,
+ MLDETECTCP_NUMBER = 16,
+} MLDETECTCP;
+
[
object,
uuid(359f3443-bd4a-11d0-b188-00aa0038c969),
@@ -677,7 +687,7 @@ interface IMultiLanguage2 : IUnknown
[in,out] INT *pnScores);
HRESULT DetectInputCodepage(
- [in] DWORD dwFlag,
+ [in] MLDETECTCP dwFlag,
[in] DWORD dwPrefWinCodePage,
[in] CHAR *pSrcStr,
[in,out] INT *pcSrcSize,
--
2.19.1
2
2
[PATCH v3 1/8] comctl32/tests: Test for LB_SETCOUNT without LBS_NODATA
by Gabriel Ivăncescu 11 Nov '18
by Gabriel Ivăncescu 11 Nov '18
11 Nov '18
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
v3: Fix the tests on broken Windows versions (only on WOW64) and place the
tests at the beginning of the patchset. Hopefully this should be enough now.
dlls/comctl32/tests/listbox.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/dlls/comctl32/tests/listbox.c b/dlls/comctl32/tests/listbox.c
index d4bb2cc..60aa59a 100644
--- a/dlls/comctl32/tests/listbox.c
+++ b/dlls/comctl32/tests/listbox.c
@@ -1766,6 +1766,13 @@ static void test_set_count( void )
GetUpdateRect( listbox, &r, TRUE );
ok( !IsRectEmpty( &r ), "got empty rect\n");
+ DestroyWindow( listbox );
+
+ listbox = create_listbox( LBS_OWNERDRAWFIXED | WS_CHILD | WS_VISIBLE, parent );
+
+ ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
+ todo_wine ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
+
DestroyWindow( listbox );
DestroyWindow( parent );
}
--
2.19.1
2
15
---
dlls/user32/combo.c | 847 +++++++++++++++++++++++---------------------
1 file changed, 445 insertions(+), 402 deletions(-)
diff --git a/dlls/user32/combo.c b/dlls/user32/combo.c
index 31ec6af526..8b7cd17909 100644
--- a/dlls/user32/combo.c
+++ b/dlls/user32/combo.c
@@ -132,9 +132,9 @@ static BOOL COMBO_Init(void)
*/
static LRESULT COMBO_NCCreate(HWND hwnd, LONG style)
{
- LPHEADCOMBO lphc;
+ HEADCOMBO *lphc;
- if (COMBO_Init() && (lphc = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(HEADCOMBO))) )
+ if (COMBO_Init() && (lphc = heap_alloc_zero(sizeof(*lphc))))
{
lphc->self = hwnd;
SetWindowLongPtrW( hwnd, 0, (LONG_PTR)lphc );
@@ -165,20 +165,20 @@ static LRESULT COMBO_NCCreate(HWND hwnd, LONG style)
/***********************************************************************
* COMBO_NCDestroy
*/
-static LRESULT COMBO_NCDestroy( LPHEADCOMBO lphc )
+static LRESULT COMBO_NCDestroy( HEADCOMBO *lphc )
{
+ if (lphc)
+ {
+ TRACE("[%p]: freeing storage\n", lphc->self);
- if( lphc )
- {
- TRACE("[%p]: freeing storage\n", lphc->self);
+ if ( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
+ DestroyWindow( lphc->hWndLBox );
- if( (CB_GETTYPE(lphc) != CBS_SIMPLE) && lphc->hWndLBox )
- DestroyWindow( lphc->hWndLBox );
+ SetWindowLongPtrW( lphc->self, 0, 0 );
+ heap_free( lphc );
+ }
- SetWindowLongPtrW( lphc->self, 0, 0 );
- HeapFree( GetProcessHeap(), 0, lphc );
- }
- return 0;
+ return 0;
}
/***********************************************************************
@@ -684,9 +684,7 @@ static HBRUSH COMBO_PrepareColors(
*
* Paint CBS_DROPDOWNLIST text field / update edit control contents.
*/
-static void CBPaintText(
- LPHEADCOMBO lphc,
- HDC hdc_paint)
+static void CBPaintText(HEADCOMBO *lphc, HDC hdc_paint)
{
RECT rectEdit = lphc->textRect;
INT id, size = 0;
@@ -702,7 +700,7 @@ static void CBPaintText(
size = SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, id, 0);
if (size == LB_ERR)
FIXME("LB_ERR probably not handled yet\n");
- if( (pText = HeapAlloc( GetProcessHeap(), 0, (size + 1) * sizeof(WCHAR))) )
+ if ((pText = heap_alloc((size + 1) * sizeof(WCHAR))))
{
/* size from LB_GETTEXTLEN may be too large, from LB_GETTEXT is accurate */
size=SendMessageW(lphc->hWndLBox, LB_GETTEXT, id, (LPARAM)pText);
@@ -800,7 +798,8 @@ static void CBPaintText(
if( !hdc_paint )
ReleaseDC( lphc->self, hdc );
}
- HeapFree( GetProcessHeap(), 0, pText );
+
+ heap_free(pText);
}
/***********************************************************************
@@ -901,8 +900,8 @@ static INT CBUpdateLBox( LPHEADCOMBO lphc, BOOL bSelect )
idx = LB_ERR;
length = SendMessageW( lphc->hWndEdit, WM_GETTEXTLENGTH, 0, 0 );
- if( length > 0 )
- pText = HeapAlloc( GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR));
+ if (length > 0)
+ pText = heap_alloc((length + 1) * sizeof(WCHAR));
TRACE("\t edit text length %i\n", length );
@@ -910,7 +909,7 @@ static INT CBUpdateLBox( LPHEADCOMBO lphc, BOOL bSelect )
{
GetWindowTextW( lphc->hWndEdit, pText, length + 1);
idx = SendMessageW(lphc->hWndLBox, LB_FINDSTRING, -1, (LPARAM)pText);
- HeapFree( GetProcessHeap(), 0, pText );
+ heap_free( pText );
}
SendMessageW(lphc->hWndLBox, LB_SETCURSEL, bSelect ? idx : -1, 0);
@@ -940,10 +939,8 @@ static void CBUpdateEdit( LPHEADCOMBO lphc , INT index )
length = SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, index, 0);
if( length != LB_ERR)
{
- if( (pText = HeapAlloc( GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR))) )
- {
+ if ((pText = heap_alloc((length + 1) * sizeof(WCHAR))))
SendMessageW(lphc->hWndLBox, LB_GETTEXT, index, (LPARAM)pText);
- }
}
}
@@ -957,7 +954,7 @@ static void CBUpdateEdit( LPHEADCOMBO lphc , INT index )
if( lphc->wState & CBF_FOCUSED )
SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, -1);
- HeapFree( GetProcessHeap(), 0, pText );
+ heap_free( pText );
}
/***********************************************************************
@@ -1178,7 +1175,7 @@ static void COMBO_KillFocus( LPHEADCOMBO lphc )
if( CB_GETTYPE(lphc) == CBS_DROPDOWNLIST )
SendMessageW(lphc->hWndLBox, LB_CARETOFF, 0, 0);
- lphc->wState &= ~CBF_FOCUSED;
+ lphc->wState &= ~CBF_FOCUSED;
/* redraw text */
if( !(lphc->wState & CBF_EDIT) )
@@ -1349,7 +1346,7 @@ static LRESULT COMBO_ItemOp( LPHEADCOMBO lphc, UINT msg, LPARAM lParam )
/***********************************************************************
* COMBO_GetTextW
*/
-static LRESULT COMBO_GetTextW( LPHEADCOMBO lphc, INT count, LPWSTR buf )
+static LRESULT COMBO_GetTextW( HEADCOMBO *lphc, INT count, LPWSTR buf )
{
INT length;
@@ -1369,7 +1366,7 @@ static LRESULT COMBO_GetTextW( LPHEADCOMBO lphc, INT count, LPWSTR buf )
/* 'length' is without the terminating character */
if (length >= count)
{
- LPWSTR lpBuffer = HeapAlloc(GetProcessHeap(), 0, (length + 1) * sizeof(WCHAR));
+ WCHAR *lpBuffer = heap_alloc((length + 1) * sizeof(WCHAR));
if (!lpBuffer) goto error;
length = SendMessageW(lphc->hWndLBox, LB_GETTEXT, idx, (LPARAM)lpBuffer);
@@ -1379,7 +1376,7 @@ static LRESULT COMBO_GetTextW( LPHEADCOMBO lphc, INT count, LPWSTR buf )
lstrcpynW( buf, lpBuffer, count );
length = count;
}
- HeapFree( GetProcessHeap(), 0, lpBuffer );
+ heap_free( lpBuffer );
}
else length = SendMessageW(lphc->hWndLBox, LB_GETTEXT, idx, (LPARAM)buf);
@@ -1786,393 +1783,439 @@ static char *strdupA(LPCSTR str)
*/
LRESULT ComboWndProc_common( HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam, BOOL unicode )
{
- LPHEADCOMBO lphc = (LPHEADCOMBO)GetWindowLongPtrW( hwnd, 0 );
+ HEADCOMBO *lphc = (HEADCOMBO *)GetWindowLongPtrW( hwnd, 0 );
- TRACE("[%p]: msg %s wp %08lx lp %08lx\n",
- hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam );
+ TRACE("[%p]: msg %s wp %08lx lp %08lx\n",
+ hwnd, SPY_GetMsgName(message, hwnd), wParam, lParam );
- if (!IsWindow(hwnd)) return 0;
+ if (!IsWindow(hwnd)) return 0;
- if( lphc || message == WM_NCCREATE )
- switch(message)
- {
+ if (lphc || message == WM_NCCREATE)
+ switch(message)
+ {
- /* System messages */
+ /* System messages */
- case WM_NCCREATE:
- {
- LONG style = unicode ? ((LPCREATESTRUCTW)lParam)->style :
- ((LPCREATESTRUCTA)lParam)->style;
- return COMBO_NCCreate(hwnd, style);
- }
- case WM_NCDESTROY:
- COMBO_NCDestroy(lphc);
- break;/* -> DefWindowProc */
-
- case WM_CREATE:
- {
- HWND hwndParent;
- LONG style;
- if(unicode)
- {
- hwndParent = ((LPCREATESTRUCTW)lParam)->hwndParent;
- style = ((LPCREATESTRUCTW)lParam)->style;
- }
- else
- {
- hwndParent = ((LPCREATESTRUCTA)lParam)->hwndParent;
- style = ((LPCREATESTRUCTA)lParam)->style;
- }
- return COMBO_Create(hwnd, lphc, hwndParent, style, unicode);
- }
+ case WM_NCCREATE:
+ {
+ LONG style = unicode ? ((LPCREATESTRUCTW)lParam)->style :
+ ((LPCREATESTRUCTA)lParam)->style;
+ return COMBO_NCCreate(hwnd, style);
+ }
+ case WM_NCDESTROY:
+ COMBO_NCDestroy(lphc);
+ break;/* -> DefWindowProc */
- case WM_PRINTCLIENT:
- /* Fallthrough */
- case WM_PAINT:
- /* wParam may contain a valid HDC! */
- return COMBO_Paint(lphc, (HDC)wParam);
+ case WM_CREATE:
+ {
+ HWND hwndParent;
+ LONG style;
+ if(unicode)
+ {
+ hwndParent = ((LPCREATESTRUCTW)lParam)->hwndParent;
+ style = ((LPCREATESTRUCTW)lParam)->style;
+ }
+ else
+ {
+ hwndParent = ((LPCREATESTRUCTA)lParam)->hwndParent;
+ style = ((LPCREATESTRUCTA)lParam)->style;
+ }
+ return COMBO_Create(hwnd, lphc, hwndParent, style, unicode);
+ }
- case WM_ERASEBKGND:
- /* do all painting in WM_PAINT like Windows does */
- return 1;
+ case WM_PRINTCLIENT:
+ case WM_PAINT:
+ /* wParam may contain a valid HDC! */
+ return COMBO_Paint(lphc, (HDC)wParam);
- case WM_GETDLGCODE:
- {
- LRESULT result = DLGC_WANTARROWS | DLGC_WANTCHARS;
- if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
- {
- int vk = (int)((LPMSG)lParam)->wParam;
+ case WM_ERASEBKGND:
+ /* do all painting in WM_PAINT like Windows does */
+ return 1;
- if ((vk == VK_RETURN || vk == VK_ESCAPE) && (lphc->wState & CBF_DROPPED))
- result |= DLGC_WANTMESSAGE;
- }
- return result;
- }
- case WM_SIZE:
- if( lphc->hWndLBox &&
- !(lphc->wState & CBF_NORESIZE) ) COMBO_Size( lphc );
- return TRUE;
- case WM_SETFONT:
- COMBO_Font( lphc, (HFONT)wParam, (BOOL)lParam );
- return TRUE;
- case WM_GETFONT:
- return (LRESULT)lphc->hFont;
- case WM_SETFOCUS:
- if( lphc->wState & CBF_EDIT ) {
- SetFocus( lphc->hWndEdit );
- /* The first time focus is received, select all the text */
- if( !(lphc->wState & CBF_BEENFOCUSED) ) {
- SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, -1);
- lphc->wState |= CBF_BEENFOCUSED;
- }
- }
- else
- COMBO_SetFocus( lphc );
- return TRUE;
- case WM_KILLFOCUS:
+ case WM_GETDLGCODE:
+ {
+ LRESULT result = DLGC_WANTARROWS | DLGC_WANTCHARS;
+ if (lParam && (((LPMSG)lParam)->message == WM_KEYDOWN))
+ {
+ int vk = (int)((LPMSG)lParam)->wParam;
+
+ if ((vk == VK_RETURN || vk == VK_ESCAPE) && (lphc->wState & CBF_DROPPED))
+ result |= DLGC_WANTMESSAGE;
+ }
+ return result;
+ }
+
+ case WM_SIZE:
+ if (lphc->hWndLBox && !(lphc->wState & CBF_NORESIZE))
+ COMBO_Size( lphc );
+ return TRUE;
+
+ case WM_SETFONT:
+ COMBO_Font( lphc, (HFONT)wParam, (BOOL)lParam );
+ return TRUE;
+
+ case WM_GETFONT:
+ return (LRESULT)lphc->hFont;
+
+ case WM_SETFOCUS:
+ if (lphc->wState & CBF_EDIT)
+ {
+ SetFocus( lphc->hWndEdit );
+ /* The first time focus is received, select all the text */
+ if (!(lphc->wState & CBF_BEENFOCUSED))
{
- HWND hwndFocus = WIN_GetFullHandle( (HWND)wParam );
- if( !hwndFocus ||
- (hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox ))
- COMBO_KillFocus( lphc );
- return TRUE;
+ SendMessageW(lphc->hWndEdit, EM_SETSEL, 0, -1);
+ lphc->wState |= CBF_BEENFOCUSED;
}
- case WM_COMMAND:
- return COMBO_Command( lphc, wParam, WIN_GetFullHandle( (HWND)lParam ) );
- case WM_GETTEXT:
- return unicode ? COMBO_GetTextW( lphc, wParam, (LPWSTR)lParam )
- : COMBO_GetTextA( lphc, wParam, (LPSTR)lParam );
- case WM_SETTEXT:
- case WM_GETTEXTLENGTH:
- case WM_CLEAR:
- if ((message == WM_GETTEXTLENGTH) && !ISWIN31 && !(lphc->wState & CBF_EDIT))
- {
- int j = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
- if (j == -1) return 0;
- return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, j, 0) :
- SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, j, 0);
- }
- else if( lphc->wState & CBF_EDIT )
- {
- LRESULT ret;
- lphc->wState |= CBF_NOEDITNOTIFY;
- ret = unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) :
- SendMessageA(lphc->hWndEdit, message, wParam, lParam);
- lphc->wState &= ~CBF_NOEDITNOTIFY;
- return ret;
- }
- else return CB_ERR;
- case WM_CUT:
- case WM_PASTE:
- case WM_COPY:
- if( lphc->wState & CBF_EDIT )
- {
- return unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) :
- SendMessageA(lphc->hWndEdit, message, wParam, lParam);
- }
- else return CB_ERR;
-
- case WM_DRAWITEM:
- case WM_DELETEITEM:
- case WM_COMPAREITEM:
- case WM_MEASUREITEM:
- return COMBO_ItemOp(lphc, message, lParam);
- case WM_ENABLE:
- if( lphc->wState & CBF_EDIT )
- EnableWindow( lphc->hWndEdit, (BOOL)wParam );
- EnableWindow( lphc->hWndLBox, (BOOL)wParam );
-
- /* Force the control to repaint when the enabled state changes. */
- InvalidateRect(lphc->self, NULL, TRUE);
- return TRUE;
- case WM_SETREDRAW:
- if( wParam )
- lphc->wState &= ~CBF_NOREDRAW;
- else
- lphc->wState |= CBF_NOREDRAW;
-
- if( lphc->wState & CBF_EDIT )
- SendMessageW(lphc->hWndEdit, message, wParam, lParam);
- SendMessageW(lphc->hWndLBox, message, wParam, lParam);
- return 0;
- case WM_SYSKEYDOWN:
- if( KEYDATA_ALT & HIWORD(lParam) )
- if( wParam == VK_UP || wParam == VK_DOWN )
- COMBO_FlipListbox( lphc, FALSE, FALSE );
- return 0;
-
- case WM_KEYDOWN:
- if ((wParam == VK_RETURN || wParam == VK_ESCAPE) &&
- (lphc->wState & CBF_DROPPED))
- {
- CBRollUp( lphc, wParam == VK_RETURN, FALSE );
- return TRUE;
- }
- else if ((wParam == VK_F4) && !(lphc->wState & CBF_EUI))
- {
- COMBO_FlipListbox( lphc, FALSE, FALSE );
- return TRUE;
- }
- /* fall through */
- case WM_CHAR:
- case WM_IME_CHAR:
- {
- HWND hwndTarget;
+ }
+ else
+ COMBO_SetFocus( lphc );
+ return TRUE;
- if( lphc->wState & CBF_EDIT )
- hwndTarget = lphc->hWndEdit;
- else
- hwndTarget = lphc->hWndLBox;
-
- return unicode ? SendMessageW(hwndTarget, message, wParam, lParam) :
- SendMessageA(hwndTarget, message, wParam, lParam);
- }
- case WM_LBUTTONDOWN:
- if( !(lphc->wState & CBF_FOCUSED) ) SetFocus( lphc->self );
- if( lphc->wState & CBF_FOCUSED ) COMBO_LButtonDown( lphc, lParam );
- return TRUE;
- case WM_LBUTTONUP:
- COMBO_LButtonUp( lphc );
- return TRUE;
- case WM_MOUSEMOVE:
- if( lphc->wState & CBF_CAPTURE )
- COMBO_MouseMove( lphc, wParam, lParam );
- return TRUE;
-
- case WM_MOUSEWHEEL:
- if (wParam & (MK_SHIFT | MK_CONTROL))
- return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
- DefWindowProcA(hwnd, message, wParam, lParam);
-
- if (GET_WHEEL_DELTA_WPARAM(wParam) > 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_UP, 0);
- if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_DOWN, 0);
- return TRUE;
-
- /* Combo messages */
-
- case CB_ADDSTRING:
- if( unicode )
- {
- if( lphc->dwStyle & CBS_LOWERCASE )
- CharLowerW((LPWSTR)lParam);
- else if( lphc->dwStyle & CBS_UPPERCASE )
- CharUpperW((LPWSTR)lParam);
- return SendMessageW(lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
- }
- else /* unlike the unicode version, the ansi version does not overwrite
- the string if converting case */
- {
- char *string = NULL;
- LRESULT ret;
- if( lphc->dwStyle & CBS_LOWERCASE )
- {
- string = strdupA((LPSTR)lParam);
- CharLowerA(string);
- }
-
- else if( lphc->dwStyle & CBS_UPPERCASE )
- {
- string = strdupA((LPSTR)lParam);
- CharUpperA(string);
- }
-
- ret = SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, string ? (LPARAM)string : lParam);
- HeapFree(GetProcessHeap(), 0, string);
- return ret;
- }
- case CB_INSERTSTRING:
- if( unicode )
- {
- if( lphc->dwStyle & CBS_LOWERCASE )
- CharLowerW((LPWSTR)lParam);
- else if( lphc->dwStyle & CBS_UPPERCASE )
- CharUpperW((LPWSTR)lParam);
- return SendMessageW(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
- }
- else
- {
- if( lphc->dwStyle & CBS_LOWERCASE )
- CharLowerA((LPSTR)lParam);
- else if( lphc->dwStyle & CBS_UPPERCASE )
- CharUpperA((LPSTR)lParam);
+ case WM_KILLFOCUS:
+ {
+ HWND hwndFocus = WIN_GetFullHandle( (HWND)wParam );
+ if (!hwndFocus || (hwndFocus != lphc->hWndEdit && hwndFocus != lphc->hWndLBox))
+ COMBO_KillFocus( lphc );
+ return TRUE;
+ }
- return SendMessageA(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
- }
- case CB_DELETESTRING:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_DELETESTRING, wParam, 0) :
- SendMessageA(lphc->hWndLBox, LB_DELETESTRING, wParam, 0);
- case CB_SELECTSTRING:
- return COMBO_SelectString(lphc, (INT)wParam, lParam, unicode);
- case CB_FINDSTRING:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam) :
- SendMessageA(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam);
- case CB_FINDSTRINGEXACT:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam) :
- SendMessageA(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam);
- case CB_SETITEMHEIGHT:
- return COMBO_SetItemHeight( lphc, (INT)wParam, (INT)lParam);
- case CB_GETITEMHEIGHT:
- if( (INT)wParam >= 0 ) /* listbox item */
- return SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0);
- return CBGetTextAreaHeight(hwnd, lphc);
- case CB_RESETCONTENT:
- SendMessageW(lphc->hWndLBox, LB_RESETCONTENT, 0, 0);
- if( (lphc->wState & CBF_EDIT) && CB_HASSTRINGS(lphc) )
- {
- static const WCHAR empty_stringW[] = { 0 };
- SendMessageW(lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)empty_stringW);
- }
- else
- InvalidateRect(lphc->self, NULL, TRUE);
- return TRUE;
- case CB_INITSTORAGE:
- return SendMessageW(lphc->hWndLBox, LB_INITSTORAGE, wParam, lParam);
- case CB_GETHORIZONTALEXTENT:
- return SendMessageW(lphc->hWndLBox, LB_GETHORIZONTALEXTENT, 0, 0);
- case CB_SETHORIZONTALEXTENT:
- return SendMessageW(lphc->hWndLBox, LB_SETHORIZONTALEXTENT, wParam, 0);
- case CB_GETTOPINDEX:
- return SendMessageW(lphc->hWndLBox, LB_GETTOPINDEX, 0, 0);
- case CB_GETLOCALE:
- return SendMessageW(lphc->hWndLBox, LB_GETLOCALE, 0, 0);
- case CB_SETLOCALE:
- return SendMessageW(lphc->hWndLBox, LB_SETLOCALE, wParam, 0);
- case CB_SETDROPPEDWIDTH:
- if( (CB_GETTYPE(lphc) == CBS_SIMPLE) ||
- (INT)wParam >= 32768 )
- return CB_ERR;
- /* new value must be higher than combobox width */
- if((INT)wParam >= lphc->droppedRect.right - lphc->droppedRect.left)
- lphc->droppedWidth = wParam;
- else if(wParam)
- lphc->droppedWidth = 0;
-
- /* recalculate the combobox area */
- CBCalcPlacement(hwnd, lphc, &lphc->textRect, &lphc->buttonRect, &lphc->droppedRect );
-
- /* fall through */
- case CB_GETDROPPEDWIDTH:
- if( lphc->droppedWidth )
- return lphc->droppedWidth;
- return lphc->droppedRect.right - lphc->droppedRect.left;
- case CB_GETDROPPEDCONTROLRECT:
- if( lParam ) CBGetDroppedControlRect(lphc, (LPRECT)lParam );
- return CB_OKAY;
- case CB_GETDROPPEDSTATE:
- return (lphc->wState & CBF_DROPPED) != 0;
- case CB_DIR:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_DIR, wParam, lParam) :
- SendMessageA(lphc->hWndLBox, LB_DIR, wParam, lParam);
-
- case CB_SHOWDROPDOWN:
- if( CB_GETTYPE(lphc) != CBS_SIMPLE )
- {
- if( wParam )
- {
- if( !(lphc->wState & CBF_DROPPED) )
- CBDropDown( lphc );
- }
- else
- if( lphc->wState & CBF_DROPPED )
- CBRollUp( lphc, FALSE, TRUE );
- }
- return TRUE;
- case CB_GETCOUNT:
- return SendMessageW(lphc->hWndLBox, LB_GETCOUNT, 0, 0);
- case CB_GETCURSEL:
- return SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
- case CB_SETCURSEL:
- lParam = SendMessageW(lphc->hWndLBox, LB_SETCURSEL, wParam, 0);
- if( lParam >= 0 )
- SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, wParam, 0);
-
- /* no LBN_SELCHANGE in this case, update manually */
- CBPaintText( lphc, NULL );
- lphc->wState &= ~CBF_SELCHANGE;
- return lParam;
- case CB_GETLBTEXT:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXT, wParam, lParam) :
- SendMessageA(lphc->hWndLBox, LB_GETTEXT, wParam, lParam);
- case CB_GETLBTEXTLEN:
- return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0) :
- SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0);
- case CB_GETITEMDATA:
- return SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0);
- case CB_SETITEMDATA:
- return SendMessageW(lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam);
- case CB_GETEDITSEL:
- /* Edit checks passed parameters itself */
- if( lphc->wState & CBF_EDIT )
- return SendMessageW(lphc->hWndEdit, EM_GETSEL, wParam, lParam);
- return CB_ERR;
- case CB_SETEDITSEL:
- if( lphc->wState & CBF_EDIT )
- return SendMessageW(lphc->hWndEdit, EM_SETSEL,
- (INT)(SHORT)LOWORD(lParam), (INT)(SHORT)HIWORD(lParam) );
- return CB_ERR;
- case CB_SETEXTENDEDUI:
- if( CB_GETTYPE(lphc) == CBS_SIMPLE )
- return CB_ERR;
- if( wParam )
- lphc->wState |= CBF_EUI;
- else lphc->wState &= ~CBF_EUI;
- return CB_OKAY;
- case CB_GETEXTENDEDUI:
- return (lphc->wState & CBF_EUI) != 0;
- case CB_GETCOMBOBOXINFO:
- return COMBO_GetComboBoxInfo(lphc, (COMBOBOXINFO *)lParam);
- case CB_LIMITTEXT:
- if( lphc->wState & CBF_EDIT )
- return SendMessageW(lphc->hWndEdit, EM_LIMITTEXT, wParam, lParam);
- return TRUE;
- default:
- if (message >= WM_USER)
- WARN("unknown msg WM_USER+%04x wp=%04lx lp=%08lx\n",
- message - WM_USER, wParam, lParam );
- break;
- }
- return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
- DefWindowProcA(hwnd, message, wParam, lParam);
+ case WM_COMMAND:
+ return COMBO_Command( lphc, wParam, WIN_GetFullHandle( (HWND)lParam ) );
+
+ case WM_GETTEXT:
+ return unicode ? COMBO_GetTextW( lphc, wParam, (LPWSTR)lParam )
+ : COMBO_GetTextA( lphc, wParam, (LPSTR)lParam );
+
+ case WM_SETTEXT:
+ case WM_GETTEXTLENGTH:
+ case WM_CLEAR:
+ if ((message == WM_GETTEXTLENGTH) && !ISWIN31 && !(lphc->wState & CBF_EDIT))
+ {
+ int j = SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
+ if (j == -1) return 0;
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, j, 0) :
+ SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, j, 0);
+ }
+ else if ( lphc->wState & CBF_EDIT )
+ {
+ LRESULT ret;
+ lphc->wState |= CBF_NOEDITNOTIFY;
+ ret = unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) :
+ SendMessageA(lphc->hWndEdit, message, wParam, lParam);
+ lphc->wState &= ~CBF_NOEDITNOTIFY;
+ return ret;
+ }
+ else
+ return CB_ERR;
+
+ case WM_CUT:
+ case WM_PASTE:
+ case WM_COPY:
+ if (lphc->wState & CBF_EDIT)
+ {
+ return unicode ? SendMessageW(lphc->hWndEdit, message, wParam, lParam) :
+ SendMessageA(lphc->hWndEdit, message, wParam, lParam);
+ }
+ else return CB_ERR;
+
+ case WM_DRAWITEM:
+ case WM_DELETEITEM:
+ case WM_COMPAREITEM:
+ case WM_MEASUREITEM:
+ return COMBO_ItemOp(lphc, message, lParam);
+
+ case WM_ENABLE:
+ if (lphc->wState & CBF_EDIT)
+ EnableWindow( lphc->hWndEdit, (BOOL)wParam );
+ EnableWindow( lphc->hWndLBox, (BOOL)wParam );
+
+ /* Force the control to repaint when the enabled state changes. */
+ InvalidateRect(lphc->self, NULL, TRUE);
+ return TRUE;
+
+ case WM_SETREDRAW:
+ if (wParam)
+ lphc->wState &= ~CBF_NOREDRAW;
+ else
+ lphc->wState |= CBF_NOREDRAW;
+
+ if ( lphc->wState & CBF_EDIT )
+ SendMessageW(lphc->hWndEdit, message, wParam, lParam);
+ SendMessageW(lphc->hWndLBox, message, wParam, lParam);
+ return 0;
+
+ case WM_SYSKEYDOWN:
+ if ( KEYDATA_ALT & HIWORD(lParam) )
+ if( wParam == VK_UP || wParam == VK_DOWN )
+ COMBO_FlipListbox( lphc, FALSE, FALSE );
+ return 0;
+
+ case WM_KEYDOWN:
+ if ((wParam == VK_RETURN || wParam == VK_ESCAPE) &&
+ (lphc->wState & CBF_DROPPED))
+ {
+ CBRollUp( lphc, wParam == VK_RETURN, FALSE );
+ return TRUE;
+ }
+ else if ((wParam == VK_F4) && !(lphc->wState & CBF_EUI))
+ {
+ COMBO_FlipListbox( lphc, FALSE, FALSE );
+ return TRUE;
+ }
+ /* fall through */
+ case WM_CHAR:
+ case WM_IME_CHAR:
+ {
+ HWND hwndTarget;
+
+ if ( lphc->wState & CBF_EDIT )
+ hwndTarget = lphc->hWndEdit;
+ else
+ hwndTarget = lphc->hWndLBox;
+
+ return unicode ? SendMessageW(hwndTarget, message, wParam, lParam) :
+ SendMessageA(hwndTarget, message, wParam, lParam);
+ }
+
+ case WM_LBUTTONDOWN:
+ if ( !(lphc->wState & CBF_FOCUSED) ) SetFocus( lphc->self );
+ if ( lphc->wState & CBF_FOCUSED ) COMBO_LButtonDown( lphc, lParam );
+ return TRUE;
+
+ case WM_LBUTTONUP:
+ COMBO_LButtonUp( lphc );
+ return TRUE;
+
+ case WM_MOUSEMOVE:
+ if (lphc->wState & CBF_CAPTURE)
+ COMBO_MouseMove( lphc, wParam, lParam );
+ return TRUE;
+
+ case WM_MOUSEWHEEL:
+ if (wParam & (MK_SHIFT | MK_CONTROL))
+ return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
+ DefWindowProcA(hwnd, message, wParam, lParam);
+
+ if (GET_WHEEL_DELTA_WPARAM(wParam) > 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_UP, 0);
+ if (GET_WHEEL_DELTA_WPARAM(wParam) < 0) return SendMessageW(hwnd, WM_KEYDOWN, VK_DOWN, 0);
+ return TRUE;
+
+ /* Combo messages */
+
+ case CB_ADDSTRING:
+ if( unicode )
+ {
+ if( lphc->dwStyle & CBS_LOWERCASE )
+ CharLowerW((LPWSTR)lParam);
+ else if( lphc->dwStyle & CBS_UPPERCASE )
+ CharUpperW((LPWSTR)lParam);
+ return SendMessageW(lphc->hWndLBox, LB_ADDSTRING, 0, lParam);
+ }
+ else /* unlike the unicode version, the ansi version does not overwrite
+ the string if converting case */
+ {
+ char *string = NULL;
+ LRESULT ret;
+ if( lphc->dwStyle & CBS_LOWERCASE )
+ {
+ string = strdupA((LPSTR)lParam);
+ CharLowerA(string);
+ }
+
+ else if( lphc->dwStyle & CBS_UPPERCASE )
+ {
+ string = strdupA((LPSTR)lParam);
+ CharUpperA(string);
+ }
+
+ ret = SendMessageA(lphc->hWndLBox, LB_ADDSTRING, 0, string ? (LPARAM)string : lParam);
+ HeapFree(GetProcessHeap(), 0, string);
+ return ret;
+ }
+ case CB_INSERTSTRING:
+ if( unicode )
+ {
+ if( lphc->dwStyle & CBS_LOWERCASE )
+ CharLowerW((LPWSTR)lParam);
+ else if( lphc->dwStyle & CBS_UPPERCASE )
+ CharUpperW((LPWSTR)lParam);
+ return SendMessageW(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
+ }
+ else
+ {
+ if( lphc->dwStyle & CBS_LOWERCASE )
+ CharLowerA((LPSTR)lParam);
+ else if( lphc->dwStyle & CBS_UPPERCASE )
+ CharUpperA((LPSTR)lParam);
+
+ return SendMessageA(lphc->hWndLBox, LB_INSERTSTRING, wParam, lParam);
+ }
+ case CB_DELETESTRING:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_DELETESTRING, wParam, 0) :
+ SendMessageA(lphc->hWndLBox, LB_DELETESTRING, wParam, 0);
+
+ case CB_SELECTSTRING:
+ return COMBO_SelectString(lphc, (INT)wParam, lParam, unicode);
+
+ case CB_FINDSTRING:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam) :
+ SendMessageA(lphc->hWndLBox, LB_FINDSTRING, wParam, lParam);
+
+ case CB_FINDSTRINGEXACT:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam) :
+ SendMessageA(lphc->hWndLBox, LB_FINDSTRINGEXACT, wParam, lParam);
+
+ case CB_SETITEMHEIGHT:
+ return COMBO_SetItemHeight( lphc, (INT)wParam, (INT)lParam);
+
+ case CB_GETITEMHEIGHT:
+ if ((INT)wParam >= 0) /* listbox item */
+ return SendMessageW(lphc->hWndLBox, LB_GETITEMHEIGHT, wParam, 0);
+ return CBGetTextAreaHeight(hwnd, lphc);
+
+ case CB_RESETCONTENT:
+ SendMessageW(lphc->hWndLBox, LB_RESETCONTENT, 0, 0);
+
+ if ((lphc->wState & CBF_EDIT) && CB_HASSTRINGS(lphc))
+ {
+ static const WCHAR empty_stringW[] = { 0 };
+ SendMessageW(lphc->hWndEdit, WM_SETTEXT, 0, (LPARAM)empty_stringW);
+ }
+ else
+ InvalidateRect(lphc->self, NULL, TRUE);
+ return TRUE;
+
+ case CB_INITSTORAGE:
+ return SendMessageW(lphc->hWndLBox, LB_INITSTORAGE, wParam, lParam);
+
+ case CB_GETHORIZONTALEXTENT:
+ return SendMessageW(lphc->hWndLBox, LB_GETHORIZONTALEXTENT, 0, 0);
+
+ case CB_SETHORIZONTALEXTENT:
+ return SendMessageW(lphc->hWndLBox, LB_SETHORIZONTALEXTENT, wParam, 0);
+
+ case CB_GETTOPINDEX:
+ return SendMessageW(lphc->hWndLBox, LB_GETTOPINDEX, 0, 0);
+
+ case CB_GETLOCALE:
+ return SendMessageW(lphc->hWndLBox, LB_GETLOCALE, 0, 0);
+
+ case CB_SETLOCALE:
+ return SendMessageW(lphc->hWndLBox, LB_SETLOCALE, wParam, 0);
+
+ case CB_SETDROPPEDWIDTH:
+ if ((CB_GETTYPE(lphc) == CBS_SIMPLE) || (INT)wParam >= 32768)
+ return CB_ERR;
+
+ /* new value must be higher than combobox width */
+ if ((INT)wParam >= lphc->droppedRect.right - lphc->droppedRect.left)
+ lphc->droppedWidth = wParam;
+ else if (wParam)
+ lphc->droppedWidth = 0;
+
+ /* recalculate the combobox area */
+ CBCalcPlacement(hwnd, lphc, &lphc->textRect, &lphc->buttonRect, &lphc->droppedRect );
+
+ /* fall through */
+ case CB_GETDROPPEDWIDTH:
+ if (lphc->droppedWidth)
+ return lphc->droppedWidth;
+ return lphc->droppedRect.right - lphc->droppedRect.left;
+
+ case CB_GETDROPPEDCONTROLRECT:
+ if (lParam)
+ CBGetDroppedControlRect(lphc, (LPRECT)lParam );
+ return CB_OKAY;
+
+ case CB_GETDROPPEDSTATE:
+ return (lphc->wState & CBF_DROPPED) != 0;
+
+ case CB_DIR:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_DIR, wParam, lParam) :
+ SendMessageA(lphc->hWndLBox, LB_DIR, wParam, lParam);
+
+ case CB_SHOWDROPDOWN:
+ if (CB_GETTYPE(lphc) != CBS_SIMPLE)
+ {
+ if (wParam)
+ {
+ if (!(lphc->wState & CBF_DROPPED))
+ CBDropDown( lphc );
+ }
+ else if (lphc->wState & CBF_DROPPED)
+ CBRollUp( lphc, FALSE, TRUE );
+ }
+ return TRUE;
+
+ case CB_GETCOUNT:
+ return SendMessageW(lphc->hWndLBox, LB_GETCOUNT, 0, 0);
+
+ case CB_GETCURSEL:
+ return SendMessageW(lphc->hWndLBox, LB_GETCURSEL, 0, 0);
+
+ case CB_SETCURSEL:
+ lParam = SendMessageW(lphc->hWndLBox, LB_SETCURSEL, wParam, 0);
+ if (lParam >= 0)
+ SendMessageW(lphc->hWndLBox, LB_SETTOPINDEX, wParam, 0);
+
+ /* no LBN_SELCHANGE in this case, update manually */
+ CBPaintText(lphc, NULL);
+ lphc->wState &= ~CBF_SELCHANGE;
+ return lParam;
+
+ case CB_GETLBTEXT:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXT, wParam, lParam) :
+ SendMessageA(lphc->hWndLBox, LB_GETTEXT, wParam, lParam);
+
+ case CB_GETLBTEXTLEN:
+ return unicode ? SendMessageW(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0) :
+ SendMessageA(lphc->hWndLBox, LB_GETTEXTLEN, wParam, 0);
+
+ case CB_GETITEMDATA:
+ return SendMessageW(lphc->hWndLBox, LB_GETITEMDATA, wParam, 0);
+
+ case CB_SETITEMDATA:
+ return SendMessageW(lphc->hWndLBox, LB_SETITEMDATA, wParam, lParam);
+
+ case CB_GETEDITSEL:
+ /* Edit checks passed parameters itself */
+ if (lphc->wState & CBF_EDIT)
+ return SendMessageW(lphc->hWndEdit, EM_GETSEL, wParam, lParam);
+ return CB_ERR;
+
+ case CB_SETEDITSEL:
+ if (lphc->wState & CBF_EDIT)
+ return SendMessageW(lphc->hWndEdit, EM_SETSEL, (INT)(SHORT)LOWORD(lParam), (INT)(SHORT)HIWORD(lParam) );
+ return CB_ERR;
+
+ case CB_SETEXTENDEDUI:
+ if (CB_GETTYPE(lphc) == CBS_SIMPLE )
+ return CB_ERR;
+ if (wParam)
+ lphc->wState |= CBF_EUI;
+ else
+ lphc->wState &= ~CBF_EUI;
+ return CB_OKAY;
+
+ case CB_GETEXTENDEDUI:
+ return (lphc->wState & CBF_EUI) != 0;
+
+ case CB_GETCOMBOBOXINFO:
+ return COMBO_GetComboBoxInfo(lphc, (COMBOBOXINFO *)lParam);
+
+ case CB_LIMITTEXT:
+ if (lphc->wState & CBF_EDIT)
+ return SendMessageW(lphc->hWndEdit, EM_LIMITTEXT, wParam, lParam);
+ return TRUE;
+
+ default:
+ if (message >= WM_USER)
+ WARN("unknown msg WM_USER+%04x wp=%04lx lp=%08lx\n", message - WM_USER, wParam, lParam );
+ break;
+ }
+ return unicode ? DefWindowProcW(hwnd, message, wParam, lParam) :
+ DefWindowProcA(hwnd, message, wParam, lParam);
}
/*************************************************************************
--
2.19.1
3
5
[v5 PATCH 1/4] comctl32/tests: Add more Listbox tests for ownerdraw styles.
by Nikolay Sivov 11 Nov '18
by Nikolay Sivov 11 Nov '18
11 Nov '18
From: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/comctl32/tests/listbox.c | 50 +++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/dlls/comctl32/tests/listbox.c b/dlls/comctl32/tests/listbox.c
index d4bb2cc2a8..c118047b4f 100644
--- a/dlls/comctl32/tests/listbox.c
+++ b/dlls/comctl32/tests/listbox.c
@@ -433,6 +433,35 @@ static void test_ownerdraw(void)
ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
DestroyWindow(hLB);
+
+ /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
+ hLB = CreateWindowA(WC_LISTBOXA, "TestList", LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE, 0, 0, 100, 100,
+ NULL, NULL, NULL, 0);
+ ok(hLB != NULL, "last error 0x%08x\n", GetLastError());
+
+ ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 13);
+ ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
+ ok(ret == 13, "Unexpected item height %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 1, 42);
+ ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
+todo_wine
+ ok(ret == 42, "Unexpected item height %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 1, 0);
+ ok(ret == 42, "Unexpected item height %d.\n", ret);
+
+ DestroyWindow (hLB);
+
DestroyWindow(parent);
}
@@ -1737,7 +1766,13 @@ static void test_listbox_dlgdir(void)
static void test_set_count( void )
{
+ static const DWORD styles[] =
+ {
+ LBS_OWNERDRAWFIXED,
+ LBS_HASSTRINGS,
+ };
HWND parent, listbox;
+ unsigned int i;
LONG ret;
RECT r;
@@ -1767,6 +1802,21 @@ static void test_set_count( void )
ok( !IsRectEmpty( &r ), "got empty rect\n");
DestroyWindow( listbox );
+
+ for (i = 0; i < ARRAY_SIZE(styles); ++i)
+ {
+ listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent );
+
+ SetLastError( 0xdeadbeef );
+ ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
+ todo_wine_if(i == 0)
+ ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
+ todo_wine_if(i == 1)
+ ok( GetLastError() == 0xdeadbeef, "Unexpected error %d.\n", GetLastError() );
+
+ DestroyWindow( listbox );
+ }
+
DestroyWindow( parent );
}
--
2.19.1
1
3
[PATCH] dwrite: Improve returned font metrics when OS/2 table is missing.
by Nikolay Sivov 11 Nov '18
by Nikolay Sivov 11 Nov '18
11 Nov '18
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/dwrite/opentype.c | 7 ++
dlls/dwrite/tests/font.c | 211 +++++++++++++++++++++++----------------
2 files changed, 130 insertions(+), 88 deletions(-)
diff --git a/dlls/dwrite/opentype.c b/dlls/dwrite/opentype.c
index db44368b2f..db7dabcd56 100644
--- a/dlls/dwrite/opentype.c
+++ b/dlls/dwrite/opentype.c
@@ -1309,6 +1309,13 @@ void opentype_get_font_metrics(struct file_stream_desc *stream_desc, DWRITE_FONT
metrics->hasTypographicMetrics = TRUE;
}
}
+ else {
+ metrics->strikethroughPosition = metrics->designUnitsPerEm / 3;
+ if (tt_hhea) {
+ metrics->ascent = GET_BE_WORD(tt_hhea->ascender);
+ metrics->descent = abs((SHORT)GET_BE_WORD(tt_hhea->descender));
+ }
+ }
if (tt_post) {
metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition);
diff --git a/dlls/dwrite/tests/font.c b/dlls/dwrite/tests/font.c
index f21aecdd5d..29fa2f3b53 100644
--- a/dlls/dwrite/tests/font.c
+++ b/dlls/dwrite/tests/font.c
@@ -511,6 +511,27 @@ static void _delete_testfontfile(const WCHAR *filename, int line)
ok_(__FILE__,line)(ret, "failed to delete file %s, error %d\n", wine_dbgstr_w(filename), GetLastError());
}
+static void get_combined_font_name(const WCHAR *familyW, const WCHAR *faceW, WCHAR *nameW)
+{
+ static const WCHAR spaceW[] = {' ', 0};
+ lstrcpyW(nameW, familyW);
+ lstrcatW(nameW, spaceW);
+ lstrcatW(nameW, faceW);
+}
+
+static BOOL has_face_variations(IDWriteFontFace *fontface)
+{
+ IDWriteFontFace5 *fontface5;
+ BOOL ret = FALSE;
+
+ if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace5, (void **)&fontface5))) {
+ ret = IDWriteFontFace5_HasVariations(fontface5);
+ IDWriteFontFace5_Release(fontface5);
+ }
+
+ return ret;
+}
+
struct test_fontenumerator
{
IDWriteFontFileEnumerator IDWriteFontFileEnumerator_iface;
@@ -1916,6 +1937,13 @@ static void get_expected_font_metrics(IDWriteFontFace *fontface, DWRITE_FONT_MET
metrics->superscriptSizeX = GET_BE_WORD(tt_os2->ySuperscriptXSize);
metrics->superscriptSizeY = GET_BE_WORD(tt_os2->ySuperscriptYSize);
}
+ else {
+ metrics->strikethroughPosition = metrics->designUnitsPerEm / 3;
+ if (tt_hhea) {
+ metrics->ascent = GET_BE_WORD(tt_hhea->ascender);
+ metrics->descent = abs((SHORT)GET_BE_WORD(tt_hhea->descender));
+ }
+ }
if (tt_post) {
metrics->underlinePosition = GET_BE_WORD(tt_post->underlinePosition);
@@ -1937,55 +1965,72 @@ static void get_expected_font_metrics(IDWriteFontFace *fontface, DWRITE_FONT_MET
IDWriteFontFace_ReleaseFontTable(fontface, post_context);
}
-static void check_font_metrics(const WCHAR *nameW, BOOL has_metrics1, const DWRITE_FONT_METRICS *got,
- const DWRITE_FONT_METRICS1 *expected)
+static void check_font_metrics(const WCHAR *nameW, IDWriteFontFace *fontface, const DWRITE_FONT_METRICS1 *expected)
{
- ok(got->designUnitsPerEm == expected->designUnitsPerEm, "font %s: designUnitsPerEm %u, expected %u\n",
- wine_dbgstr_w(nameW), got->designUnitsPerEm, expected->designUnitsPerEm);
- ok(got->ascent == expected->ascent, "font %s: ascent %u, expected %u\n", wine_dbgstr_w(nameW), got->ascent,
+ IDWriteFontFace1 *fontface1 = NULL;
+ DWRITE_FONT_METRICS1 metrics;
+ DWORD simulations;
+ BOOL has_metrics1;
+
+ has_metrics1 = SUCCEEDED(IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void **)&fontface1));
+ simulations = IDWriteFontFace_GetSimulations(fontface);
+
+ if (fontface1) {
+ IDWriteFontFace1_GetMetrics(fontface1, &metrics);
+ IDWriteFontFace1_Release(fontface1);
+ }
+ else
+ IDWriteFontFace_GetMetrics(fontface, (DWRITE_FONT_METRICS *)&metrics);
+
+ ok(metrics.designUnitsPerEm == expected->designUnitsPerEm, "font %s: designUnitsPerEm %u, expected %u\n",
+ wine_dbgstr_w(nameW), metrics.designUnitsPerEm, expected->designUnitsPerEm);
+ ok(metrics.ascent == expected->ascent, "font %s: ascent %u, expected %u\n", wine_dbgstr_w(nameW), metrics.ascent,
expected->ascent);
- ok(got->descent == expected->descent, "font %s: descent %u, expected %u\n", wine_dbgstr_w(nameW), got->descent,
- expected->descent);
- ok(got->lineGap == expected->lineGap, "font %s: lineGap %d, expected %d\n", wine_dbgstr_w(nameW), got->lineGap,
- expected->lineGap);
- ok(got->underlinePosition == expected->underlinePosition, "font %s: underlinePosition %d, expected %d\n",
- wine_dbgstr_w(nameW), got->underlinePosition, expected->underlinePosition);
- ok(got->underlineThickness == expected->underlineThickness, "font %s: underlineThickness %u, "
- "expected %u\n", wine_dbgstr_w(nameW), got->underlineThickness, expected->underlineThickness);
- ok(got->strikethroughPosition == expected->strikethroughPosition, "font %s: strikethroughPosition %d, expected %d\n",
- wine_dbgstr_w(nameW), got->strikethroughPosition, expected->strikethroughPosition);
- ok(got->strikethroughThickness == expected->strikethroughThickness, "font %s: strikethroughThickness %u, "
- "expected %u\n", wine_dbgstr_w(nameW), got->strikethroughThickness, expected->strikethroughThickness);
+ ok(metrics.descent == expected->descent, "font %s: descent %u, expected %u\n", wine_dbgstr_w(nameW),
+ metrics.descent, expected->descent);
+ ok(metrics.lineGap == expected->lineGap, "font %s: lineGap %d, expected %d\n", wine_dbgstr_w(nameW),
+ metrics.lineGap, expected->lineGap);
+ ok(metrics.underlinePosition == expected->underlinePosition, "font %s: underlinePosition %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.underlinePosition, expected->underlinePosition);
+ ok(metrics.underlineThickness == expected->underlineThickness, "font %s: underlineThickness %u, "
+ "expected %u\n", wine_dbgstr_w(nameW), metrics.underlineThickness, expected->underlineThickness);
+ ok(metrics.strikethroughPosition == expected->strikethroughPosition, "font %s: strikethroughPosition %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.strikethroughPosition, expected->strikethroughPosition);
+ ok(metrics.strikethroughThickness == expected->strikethroughThickness, "font %s: strikethroughThickness %u, "
+ "expected %u\n", wine_dbgstr_w(nameW), metrics.strikethroughThickness, expected->strikethroughThickness);
if (has_metrics1) {
- const DWRITE_FONT_METRICS1 *m1 = (const DWRITE_FONT_METRICS1*)got;
- ok(m1->hasTypographicMetrics == expected->hasTypographicMetrics, "font %s: hasTypographicMetrics %d, "
- "expected %d\n", wine_dbgstr_w(nameW), m1->hasTypographicMetrics, expected->hasTypographicMetrics);
- ok(m1->glyphBoxLeft == expected->glyphBoxLeft, "font %s: glyphBoxLeft %d, expected %d\n", wine_dbgstr_w(nameW),
- m1->glyphBoxLeft, expected->glyphBoxLeft);
- ok(m1->glyphBoxTop == expected->glyphBoxTop, "font %s: glyphBoxTop %d, expected %d\n", wine_dbgstr_w(nameW),
- m1->glyphBoxTop, expected->glyphBoxTop);
- ok(m1->glyphBoxRight == expected->glyphBoxRight, "font %s: glyphBoxRight %d, expected %d\n", wine_dbgstr_w(nameW),
- m1->glyphBoxRight, expected->glyphBoxRight);
- ok(m1->glyphBoxBottom == expected->glyphBoxBottom, "font %s: glyphBoxBottom %d, expected %d\n", wine_dbgstr_w(nameW),
- m1->glyphBoxBottom, expected->glyphBoxBottom);
-
- ok(m1->subscriptPositionX == expected->subscriptPositionX, "font %s: subscriptPositionX %d, expected %d\n",
- wine_dbgstr_w(nameW), m1->subscriptPositionX, expected->subscriptPositionX);
- ok(m1->subscriptPositionY == expected->subscriptPositionY, "font %s: subscriptPositionY %d, expected %d\n",
- wine_dbgstr_w(nameW), m1->subscriptPositionY, expected->subscriptPositionY);
- ok(m1->subscriptSizeX == expected->subscriptSizeX, "font %s: subscriptSizeX %d, expected %d\n",
- wine_dbgstr_w(nameW), m1->subscriptSizeX, expected->subscriptSizeX);
- ok(m1->subscriptSizeY == expected->subscriptSizeY, "font %s: subscriptSizeY %d, expected %d\n",
- wine_dbgstr_w(nameW), m1->subscriptSizeY, expected->subscriptSizeY);
- ok(m1->superscriptPositionX == expected->superscriptPositionX, "font %s: superscriptPositionX %d, expected %d\n",
- wine_dbgstr_w(nameW), m1->superscriptPositionX, expected->superscriptPositionX);
- ok(m1->superscriptPositionY == expected->superscriptPositionY, "font %s: superscriptPositionY %d, expected %d\n",
- wine_dbgstr_w(nameW), m1->superscriptPositionY, expected->superscriptPositionY);
- ok(m1->superscriptSizeX == expected->superscriptSizeX, "font %s: superscriptSizeX %d, expected %d\n",
- wine_dbgstr_w(nameW), m1->superscriptSizeX, expected->superscriptSizeX);
- ok(m1->superscriptSizeY == expected->superscriptSizeY, "font %s: superscriptSizeY %d, expected %d\n",
- wine_dbgstr_w(nameW), m1->superscriptSizeY, expected->superscriptSizeY);
+ /* For simulated faces metrics are adjusted. Enable tests when exact pattern is understood. */
+ if (simulations & DWRITE_FONT_SIMULATIONS_OBLIQUE)
+ return;
+
+ ok(metrics.hasTypographicMetrics == expected->hasTypographicMetrics, "font %s: hasTypographicMetrics %d, "
+ "expected %d\n", wine_dbgstr_w(nameW), metrics.hasTypographicMetrics, expected->hasTypographicMetrics);
+ ok(metrics.glyphBoxLeft == expected->glyphBoxLeft, "font %s: glyphBoxLeft %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.glyphBoxLeft, expected->glyphBoxLeft);
+ ok(metrics.glyphBoxTop == expected->glyphBoxTop, "font %s: glyphBoxTop %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.glyphBoxTop, expected->glyphBoxTop);
+ ok(metrics.glyphBoxRight == expected->glyphBoxRight, "font %s: glyphBoxRight %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.glyphBoxRight, expected->glyphBoxRight);
+ ok(metrics.glyphBoxBottom == expected->glyphBoxBottom, "font %s: glyphBoxBottom %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.glyphBoxBottom, expected->glyphBoxBottom);
+
+ ok(metrics.subscriptPositionX == expected->subscriptPositionX, "font %s: subscriptPositionX %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.subscriptPositionX, expected->subscriptPositionX);
+ ok(metrics.subscriptPositionY == expected->subscriptPositionY, "font %s: subscriptPositionY %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.subscriptPositionY, expected->subscriptPositionY);
+ ok(metrics.subscriptSizeX == expected->subscriptSizeX, "font %s: subscriptSizeX %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.subscriptSizeX, expected->subscriptSizeX);
+ ok(metrics.subscriptSizeY == expected->subscriptSizeY, "font %s: subscriptSizeY %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.subscriptSizeY, expected->subscriptSizeY);
+ ok(metrics.superscriptPositionX == expected->superscriptPositionX, "font %s: superscriptPositionX %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.superscriptPositionX, expected->superscriptPositionX);
+ ok(metrics.superscriptPositionY == expected->superscriptPositionY, "font %s: superscriptPositionY %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.superscriptPositionY, expected->superscriptPositionY);
+ ok(metrics.superscriptSizeX == expected->superscriptSizeX, "font %s: superscriptSizeX %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.superscriptSizeX, expected->superscriptSizeX);
+ ok(metrics.superscriptSizeY == expected->superscriptSizeY, "font %s: superscriptSizeY %d, expected %d\n",
+ wine_dbgstr_w(nameW), metrics.superscriptSizeY, expected->superscriptSizeY);
}
}
@@ -2195,47 +2240,53 @@ static void test_GetMetrics(void)
count = IDWriteFontCollection_GetFontFamilyCount(syscollection);
for (i = 0; i < count; i++) {
- DWRITE_FONT_METRICS1 expected_metrics, metrics1;
+ DWRITE_FONT_METRICS1 expected_metrics;
+ WCHAR familyW[256], faceW[256];
IDWriteLocalizedStrings *names;
- IDWriteFontFace1 *fontface1;
IDWriteFontFamily *family;
+ UINT32 fontcount, j;
IDWriteFont *font;
- WCHAR nameW[256];
hr = IDWriteFontCollection_GetFontFamily(syscollection, i, &family);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IDWriteFontFamily_GetFirstMatchingFont(family, DWRITE_FONT_WEIGHT_NORMAL, DWRITE_FONT_STRETCH_NORMAL,
- DWRITE_FONT_STYLE_NORMAL, &font);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ fontcount = IDWriteFontFamily_GetFontCount(family);
- hr = IDWriteFont_CreateFontFace(font, &fontface);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IDWriteFontFamily_GetFamilyNames(family, &names);
+ ok(hr == S_OK, "Failed to get family names, hr %#x.\n", hr);
+ get_enus_string(names, familyW, ARRAY_SIZE(familyW));
+ IDWriteLocalizedStrings_Release(names);
- fontface1 = NULL;
- IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace1, (void**)&fontface1);
+ for (j = 0; j < fontcount; j++) {
+ WCHAR nameW[256];
- hr = IDWriteFontFamily_GetFamilyNames(family, &names);
- ok(hr == S_OK, "got 0x%08x\n", hr);
+ hr = IDWriteFontFamily_GetFont(family, j, &font);
+ ok(hr == S_OK, "Failed to get a font, hr %#x.\n", hr);
- get_enus_string(names, nameW, ARRAY_SIZE(nameW));
+ hr = IDWriteFont_CreateFontFace(font, &fontface);
+ ok(hr == S_OK, "Failed to create face instance, hr %#x.\n", hr);
- IDWriteLocalizedStrings_Release(names);
- IDWriteFont_Release(font);
+ hr = IDWriteFont_GetFaceNames(font, &names);
+ ok(hr == S_OK, "Failed to get face names, hr %#x.\n", hr);
+ get_enus_string(names, faceW, ARRAY_SIZE(faceW));
+ IDWriteLocalizedStrings_Release(names);
- get_expected_font_metrics(fontface, &expected_metrics);
- if (fontface1) {
- IDWriteFontFace1_GetMetrics(fontface1, &metrics1);
- check_font_metrics(nameW, TRUE, (const DWRITE_FONT_METRICS*)&metrics1, &expected_metrics);
- }
- else {
- IDWriteFontFace_GetMetrics(fontface, &metrics);
- check_font_metrics(nameW, FALSE, &metrics, &expected_metrics);
+ IDWriteFont_Release(font);
+
+ get_combined_font_name(familyW, faceW, nameW);
+
+ if (has_face_variations(fontface)) {
+ skip("%s: test does not support variable fonts.\n", wine_dbgstr_w(nameW));
+ IDWriteFontFace_Release(fontface);
+ continue;
+ }
+
+ get_expected_font_metrics(fontface, &expected_metrics);
+ check_font_metrics(nameW, fontface, &expected_metrics);
+
+ IDWriteFontFace_Release(fontface);
}
- if (fontface1)
- IDWriteFontFace1_Release(fontface1);
- IDWriteFontFace_Release(fontface);
IDWriteFontFamily_Release(family);
}
IDWriteFontCollection_Release(syscollection);
@@ -2542,19 +2593,6 @@ static void get_logfont_from_font(IDWriteFont *font, LOGFONTW *logfont)
IDWriteFontFace_Release(fontface);
}
-static BOOL has_face_variations(IDWriteFontFace *fontface)
-{
- IDWriteFontFace5 *fontface5;
- BOOL ret = FALSE;
-
- if (SUCCEEDED(IDWriteFontFace_QueryInterface(fontface, &IID_IDWriteFontFace5, (void **)&fontface5))) {
- ret = IDWriteFontFace5_HasVariations(fontface5);
- IDWriteFontFace5_Release(fontface5);
- }
-
- return ret;
-}
-
static void test_ConvertFontFaceToLOGFONT(void)
{
IDWriteFontCollection *collection;
@@ -2606,7 +2644,6 @@ if (0) /* crashes on native */
font_count = IDWriteFontFamily_GetFontCount(family);
for (j = 0; j < font_count; j++) {
- static const WCHAR spaceW[] = {' ', 0};
IDWriteFontFace *fontface;
hr = IDWriteFontFamily_GetFont(family, j, &font);
@@ -2618,9 +2655,7 @@ if (0) /* crashes on native */
get_enus_string(names, facenameW, ARRAY_SIZE(facenameW));
IDWriteLocalizedStrings_Release(names);
- lstrcpyW(nameW, familynameW);
- lstrcatW(nameW, spaceW);
- lstrcatW(nameW, facenameW);
+ get_combined_font_name(familynameW, facenameW, nameW);
hr = IDWriteFont_CreateFontFace(font, &fontface);
ok(hr == S_OK, "got 0x%08x\n", hr);
--
2.19.1
1
0
Since the com simplification with the macros is probably not feasible,
here an approach that reuses an old idea - using widl to generate
a classfactory.
Feedback appreciated!
---
dlls/uiribbon/main.c | 141 ----------------
dlls/uiribbon/uiribbon.c | 8 +-
dlls/uiribbon/uiribbon_classes.idl | 1 +
tools/makedep.c | 9 +-
tools/widl/Makefile.in | 1 +
tools/widl/factory.c | 250 +++++++++++++++++++++++++++++
tools/widl/parser.y | 1 +
tools/widl/widl.c | 23 ++-
tools/widl/widl.h | 3 +
9 files changed, 291 insertions(+), 146 deletions(-)
create mode 100644 tools/widl/factory.c
diff --git a/dlls/uiribbon/main.c b/dlls/uiribbon/main.c
index a76c349ad9..b54644599f 100644
--- a/dlls/uiribbon/main.c
+++ b/dlls/uiribbon/main.c
@@ -56,147 +56,6 @@ BOOL WINAPI DllMain(HINSTANCE hInstDLL, DWORD fdwReason, LPVOID lpvReserved)
return TRUE;
}
-typedef struct {
- IClassFactory IClassFactory_iface;
-
- LONG ref;
- HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, void **ppObj);
-} IClassFactoryImpl;
-
-static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)
-{
- return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);
-}
-
-struct object_creation_info
-{
- const CLSID *clsid;
- HRESULT (*pfnCreateInstance)(IUnknown *pUnkOuter, void **ppObj);
-};
-
-static const struct object_creation_info object_creation[] =
-{
- { &CLSID_UIRibbonFramework, UIRibbonFrameworkImpl_Create },
-};
-
-static HRESULT WINAPI XFCF_QueryInterface(LPCLASSFACTORY iface,REFIID riid, void **ppobj)
-{
- IClassFactoryImpl *This = impl_from_IClassFactory(iface);
-
- if (IsEqualGUID(riid, &IID_IUnknown)
- || IsEqualGUID(riid, &IID_IClassFactory))
- {
- IClassFactory_AddRef(iface);
- *ppobj = &This->IClassFactory_iface;
- return S_OK;
- }
-
- WARN("(%p)->(%s,%p),not found\n",This,debugstr_guid(riid),ppobj);
- return E_NOINTERFACE;
-}
-
-static ULONG WINAPI XFCF_AddRef(LPCLASSFACTORY iface)
-{
- IClassFactoryImpl *This = impl_from_IClassFactory(iface);
- return InterlockedIncrement(&This->ref);
-}
-
-static ULONG WINAPI XFCF_Release(LPCLASSFACTORY iface)
-{
- IClassFactoryImpl *This = impl_from_IClassFactory(iface);
-
- ULONG ref = InterlockedDecrement(&This->ref);
-
- if (ref == 0)
- HeapFree(GetProcessHeap(), 0, This);
-
- return ref;
-}
-
-static HRESULT WINAPI XFCF_CreateInstance(LPCLASSFACTORY iface, LPUNKNOWN pOuter, REFIID riid, void **ppobj)
-{
- IClassFactoryImpl *This = impl_from_IClassFactory(iface);
- HRESULT hres;
- LPUNKNOWN punk;
-
- TRACE("(%p)->(%p,%s,%p)\n",This,pOuter,debugstr_guid(riid),ppobj);
-
- *ppobj = NULL;
- hres = This->pfnCreateInstance(pOuter, (void **) &punk);
- if (SUCCEEDED(hres)) {
- hres = IUnknown_QueryInterface(punk, riid, ppobj);
- IUnknown_Release(punk);
- }
- return hres;
-}
-
-static HRESULT WINAPI XFCF_LockServer(LPCLASSFACTORY iface, BOOL dolock)
-{
- IClassFactoryImpl *This = impl_from_IClassFactory(iface);
- FIXME("(%p)->(%d), stub!\n",This,dolock);
- return S_OK;
-}
-
-static const IClassFactoryVtbl XFCF_Vtbl =
-{
- XFCF_QueryInterface,
- XFCF_AddRef,
- XFCF_Release,
- XFCF_CreateInstance,
- XFCF_LockServer
-};
-
-/*******************************************************************************
- * Retrieves class object from a DLL object
- *
- * NOTES
- * Docs say returns STDAPI
- *
- * PARAMS
- * rclsid [I] CLSID for the class object
- * riid [I] Reference to identifier of interface for class object
- * ppv [O] Address of variable to receive interface pointer for riid
- *
- * RETURNS
- * Success: S_OK
- * Failure: CLASS_E_CLASSNOTAVAILABLE, E_OUTOFMEMORY, E_INVALIDARG,
- * E_UNEXPECTED
- */
-HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)
-{
- unsigned int i;
- IClassFactoryImpl *factory;
-
- TRACE("(%s,%s,%p)\n", debugstr_guid(rclsid), debugstr_guid(riid), ppv);
-
- if ( !IsEqualGUID( &IID_IClassFactory, riid )
- && ! IsEqualGUID( &IID_IUnknown, riid) )
- return E_NOINTERFACE;
-
- for (i = 0; i < ARRAY_SIZE(object_creation); i++)
- {
- if (IsEqualGUID(object_creation[i].clsid, rclsid))
- break;
- }
-
- if (i == ARRAY_SIZE(object_creation))
- {
- FIXME("%s: no class found.\n", debugstr_guid(rclsid));
- return CLASS_E_CLASSNOTAVAILABLE;
- }
-
- factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));
- if (factory == NULL) return E_OUTOFMEMORY;
-
- factory->IClassFactory_iface.lpVtbl = &XFCF_Vtbl;
- factory->ref = 1;
-
- factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;
-
- *ppv = &(factory->IClassFactory_iface);
- return S_OK;
-}
-
HRESULT WINAPI DllCanUnloadNow(void)
{
return S_FALSE;
diff --git a/dlls/uiribbon/uiribbon.c b/dlls/uiribbon/uiribbon.c
index 58ac51aece..5385af5430 100644
--- a/dlls/uiribbon/uiribbon.c
+++ b/dlls/uiribbon/uiribbon.c
@@ -156,7 +156,7 @@ static const IUIFrameworkVtbl IUIFramework_Vtbl =
UIRibbonFrameworkImpl_SetModes
};
-HRESULT UIRibbonFrameworkImpl_Create(IUnknown *pUnkOuter, void **ppObj)
+HRESULT UIRibbonFramework_Create(IUnknown *pUnkOuter, void **ppObj)
{
UIRibbonFrameworkImpl *object;
@@ -173,3 +173,9 @@ HRESULT UIRibbonFrameworkImpl_Create(IUnknown *pUnkOuter, void **ppObj)
return S_OK;
}
+
+HRESULT UIRibbonImageFromBitmapFactory_Create(IUnknown *unk_outer, void **obj)
+{
+ FIXME("(%p, %p) - stub!\n", unk_outer, obj);
+ return E_FAIL;
+}
diff --git a/dlls/uiribbon/uiribbon_classes.idl b/dlls/uiribbon/uiribbon_classes.idl
index bd8bdde6b6..78d79a13fc 100644
--- a/dlls/uiribbon/uiribbon_classes.idl
+++ b/dlls/uiribbon/uiribbon_classes.idl
@@ -17,5 +17,6 @@
*/
#pragma makedep register
+#pragma makedep factory
#include "uiribbon.idl"
diff --git a/tools/makedep.c b/tools/makedep.c
index e3bb04ae82..755635f5dc 100644
--- a/tools/makedep.c
+++ b/tools/makedep.c
@@ -100,6 +100,7 @@ struct incl_file
#define FLAG_RC_PO 0x010000 /* rc file contains translations */
#define FLAG_C_IMPLIB 0x020000 /* file is part of an import library */
#define FLAG_SFD_FONTS 0x040000 /* sfd file generated bitmap fonts */
+#define FLAG_IDL_FACTORY 0x080000 /* generates a factory (_f.c) file */
static const struct
{
@@ -114,7 +115,8 @@ static const struct
{ FLAG_IDL_PROXY, "_p.c" },
{ FLAG_IDL_SERVER, "_s.c" },
{ FLAG_IDL_REGISTER, "_r.res" },
- { FLAG_IDL_HEADER, ".h" }
+ { FLAG_IDL_HEADER, ".h" },
+ { FLAG_IDL_FACTORY, "_f.c" }
};
#define HASH_SIZE 997
@@ -996,6 +998,7 @@ static void parse_pragma_directive( struct file *source, char *str )
else if (!strcmp( flag, "typelib" )) source->flags |= FLAG_IDL_TYPELIB;
else if (!strcmp( flag, "register" )) source->flags |= FLAG_IDL_REGISTER;
else if (!strcmp( flag, "regtypelib" )) source->flags |= FLAG_IDL_REGTYPELIB;
+ else if (!strcmp( flag, "factory" )) source->flags |= FLAG_IDL_FACTORY;
}
else if (strendswith( source->name, ".rc" ))
{
@@ -1821,6 +1824,10 @@ static void add_generated_sources( struct makefile *make )
add_dependency( file->file, replace_extension( source->name, ".idl", ".h" ), INCL_NORMAL );
add_all_includes( make, file, file->file );
}
+ if (source->file->flags & FLAG_IDL_FACTORY)
+ {
+ add_generated_source( make, replace_extension( source->name, ".idl", "_f.c" ), NULL );
+ }
if (source->file->flags & FLAG_IDL_IDENT)
{
file = add_generated_source( make, replace_extension( source->name, ".idl", "_i.c" ), NULL );
diff --git a/tools/widl/Makefile.in b/tools/widl/Makefile.in
index e06d6cc5b3..3e725a1c69 100644
--- a/tools/widl/Makefile.in
+++ b/tools/widl/Makefile.in
@@ -4,6 +4,7 @@ MANPAGES = widl.man.in
C_SRCS = \
client.c \
expr.c \
+ factory.c \
hash.c \
header.c \
proxy.c \
diff --git a/tools/widl/factory.c b/tools/widl/factory.c
new file mode 100644
index 0000000000..4ed0459b20
--- /dev/null
+++ b/tools/widl/factory.c
@@ -0,0 +1,250 @@
+/*
+ * IDL Compiler
+ *
+ * Copyright 2018 Fabian Maurer
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
+ */
+
+#include "config.h"
+#include "wine/port.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif
+#include <string.h>
+#include <ctype.h>
+
+#include "widl.h"
+#include "utils.h"
+#include "parser.h"
+#include "header.h"
+
+#include "widltypes.h"
+#include "typegen.h"
+#include "expr.h"
+
+static FILE* factory;
+static int indent = 0;
+
+static void print_factory( const char *format, ... ) __attribute__((format (printf, 1, 2)));
+static void print_factory( const char *format, ... )
+{
+ va_list va;
+ va_start(va, format);
+ print(factory, indent, format, va);
+ va_end(va);
+}
+
+static void init_factory(void)
+{
+ if (factory) return;
+ if (!(factory = fopen(factory_name, "w")))
+ error("Could not open %s for output\n", factory_name);
+
+ print_factory("/*** Autogenerated by WIDL %s from %s - Do not edit ***/\n", PACKAGE_VERSION, input_name);
+ print_factory("#define COBJMACROS\n");
+ print_factory("#include \"%s\"\n", header_name);
+ print_factory("#include \"wine/debug.h\"\n");
+ print_factory("\n");
+ print_factory("WINE_DEFAULT_DEBUG_CHANNEL(classfactory);\n");
+ print_factory("const char *source = \"%s\";", dup_basename(input_name, ".idl"));
+ print_factory("\n");
+ print_factory("\n");
+
+}
+
+static void write_class_array(const statement_list_t *stmts)
+{
+ const statement_t *stmt;
+
+ /* Declare all functions which need to be provided for the factory */
+ LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
+ {
+ if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_COCLASS)
+ {
+ type_t *object = stmt->u.type;
+ print_factory("HRESULT %s_Create(IUnknown *unk_outer, void **obj);\n", object->name);
+ }
+ }
+ print_factory("\n");
+
+
+ print_factory("struct object_creation_info\n");
+ print_factory("{\n");
+ print_factory(" const CLSID *clsid;\n");
+ print_factory(" HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **obj);\n");
+ print_factory("};\n");
+ print_factory("\n");
+
+ print_factory("static const struct object_creation_info object_creation[] =\n");
+ print_factory("{\n");
+
+ LIST_FOR_EACH_ENTRY( stmt, stmts, const statement_t, entry )
+ {
+ if (stmt->type == STMT_TYPE && type_get_type(stmt->u.type) == TYPE_COCLASS)
+ {
+ type_t *object = stmt->u.type;
+ print_factory(" {&CLSID_%s, &%s_Create },\n", object->name, object->name);
+ }
+ }
+ print_factory("};\n");
+}
+
+void write_factory_methods(void)
+{
+ print_factory("typedef struct {\n");
+ print_factory(" IClassFactory IClassFactory_iface;\n");
+ print_factory(" LONG ref;\n");
+ print_factory(" HRESULT (*pfnCreateInstance)(IUnknown *unk_outer, void **obj);\n");
+ print_factory("} IClassFactoryImpl;\n");
+ print_factory("\n");
+
+ print_factory("static inline IClassFactoryImpl *impl_from_IClassFactory(IClassFactory *iface)\n");
+ print_factory("{\n");
+ print_factory(" return CONTAINING_RECORD(iface, IClassFactoryImpl, IClassFactory_iface);\n");
+ print_factory("}\n");
+ print_factory("\n");
+
+ print_factory("static HRESULT WINAPI classfactory_QueryInterface(IClassFactory *iface, REFIID riid, void **ppobj)\n");
+ print_factory("{\n");
+ print_factory(" IClassFactoryImpl *impl = impl_from_IClassFactory(iface);\n");
+ print_factory("\n");
+ print_factory(" if (IsEqualGUID(riid, &IID_IUnknown)\n");
+ print_factory(" || IsEqualGUID(riid, &IID_IClassFactory))\n");
+ print_factory(" {\n");
+ print_factory(" IClassFactory_AddRef(iface);\n");
+ print_factory(" *ppobj = &impl->IClassFactory_iface;\n");
+ print_factory(" return S_OK;\n");
+ print_factory(" }\n");
+ print_factory("\n");
+ print_factory(" WARN(\"%%s - (%%p)->(%%s,%%p),not found\\n\", source, impl, debugstr_guid(riid), ppobj);\n");
+ print_factory(" return E_NOINTERFACE;\n");
+ print_factory("}\n");
+ print_factory("\n");
+
+ print_factory("static ULONG WINAPI classfactory_AddRef(IClassFactory *iface)\n");
+ print_factory("{\n");
+ print_factory(" IClassFactoryImpl *This = impl_from_IClassFactory(iface);\n");
+ print_factory(" return InterlockedIncrement(&This->ref);\n");
+ print_factory("}\n");
+ print_factory("\n");
+
+ print_factory("static ULONG WINAPI classfactory_Release(IClassFactory *iface)\n");
+ print_factory("{\n");
+ print_factory(" IClassFactoryImpl *impl = impl_from_IClassFactory(iface);\n");
+ print_factory(" ULONG ref = InterlockedDecrement(&impl->ref);\n");
+ print_factory("\n");
+ print_factory(" if (ref == 0)\n");
+ print_factory(" HeapFree(GetProcessHeap(), 0, impl);\n");
+ print_factory("\n");
+ print_factory(" return ref;\n");
+ print_factory("}\n");
+ print_factory("\n");
+
+ print_factory("static HRESULT WINAPI classfactory_CreateInstance(IClassFactory *iface, IUnknown *outer_unk, REFIID riid, void **ppobj)\n");
+ print_factory("{\n");
+ print_factory(" IClassFactoryImpl *impl = impl_from_IClassFactory(iface);\n");
+ print_factory(" HRESULT hres;\n");
+ print_factory(" IUnknown *unk;\n");
+ print_factory("\n");
+ print_factory(" TRACE(\"%%s - (%%p)->(%%p,%%s,%%p)\\n\", source, impl, outer_unk, debugstr_guid(riid), ppobj);\n");
+ print_factory("\n");
+ print_factory(" *ppobj = NULL;\n");
+ print_factory(" hres = impl->pfnCreateInstance(outer_unk, (void **) &unk);\n");
+ print_factory(" if (SUCCEEDED(hres))\n");
+ print_factory(" {\n");
+ print_factory(" hres = IUnknown_QueryInterface(unk, riid, ppobj);\n");
+ print_factory(" IUnknown_Release(unk);\n");
+ print_factory(" }\n");
+ print_factory(" return hres;\n");
+ print_factory("}\n");
+ print_factory("\n");
+
+ print_factory("static HRESULT WINAPI classfactory_LockServer(IClassFactory *iface, BOOL dolock)\n");
+ print_factory("{\n");
+ print_factory(" IClassFactoryImpl *impl = impl_from_IClassFactory(iface);\n");
+ print_factory(" FIXME(\"%%s - (%%p)->(%%d), stub!\\n\", source, impl, dolock);\n");
+ print_factory(" return S_OK;\n");
+ print_factory("}\n");
+ print_factory("\n");
+
+ print_factory("static const IClassFactoryVtbl classfactory_Vtbl =\n");
+ print_factory("{\n");
+ print_factory(" classfactory_QueryInterface,\n");
+ print_factory(" classfactory_AddRef,\n");
+ print_factory(" classfactory_Release,\n");
+ print_factory(" classfactory_CreateInstance,\n");
+ print_factory(" classfactory_LockServer\n");
+ print_factory("};\n");
+ print_factory("\n");
+
+ print_factory("HRESULT WINAPI DllGetClassObject(REFCLSID rclsid, REFIID riid, void **ppv)\n");
+ print_factory("{\n");
+ print_factory(" unsigned int i;\n");
+ print_factory(" IClassFactoryImpl *factory;\n");
+ print_factory("\n");
+ print_factory(" TRACE(\"(%%s - %%s,%%s,%%p)\\n\", source, debugstr_guid(rclsid), debugstr_guid(riid), ppv);\n");
+ print_factory("\n");
+ print_factory(" if (!IsEqualGUID(&IID_IClassFactory, riid)\n");
+ print_factory(" && !IsEqualGUID( &IID_IUnknown, riid))\n");
+ print_factory(" return E_NOINTERFACE;\n");
+ print_factory("\n");
+ print_factory(" for (i = 0; i < ARRAY_SIZE(object_creation); i++)\n");
+ print_factory(" {\n");
+ print_factory(" if (IsEqualGUID(object_creation[i].clsid, rclsid))\n");
+ print_factory(" break;\n");
+ print_factory(" }\n");
+ print_factory("\n");
+ print_factory(" if (i == ARRAY_SIZE(object_creation))\n");
+ print_factory(" {\n");
+ print_factory(" FIXME(\"%%s - %%s: no class found.\\n\", source, debugstr_guid(rclsid));\n");
+ print_factory(" return CLASS_E_CLASSNOTAVAILABLE;\n");
+ print_factory(" }\n");
+ print_factory("\n");
+ print_factory(" factory = HeapAlloc(GetProcessHeap(), 0, sizeof(*factory));\n");
+ print_factory(" if (factory == NULL)\n");
+ print_factory(" return E_OUTOFMEMORY;\n");
+ print_factory("\n");
+ print_factory(" factory->IClassFactory_iface.lpVtbl = &classfactory_Vtbl;\n");
+ print_factory(" factory->ref = 1;\n");
+ print_factory("\n");
+ print_factory(" factory->pfnCreateInstance = object_creation[i].pfnCreateInstance;\n");
+ print_factory("\n");
+ print_factory(" *ppv = &factory->IClassFactory_iface;\n");
+ print_factory(" return S_OK;\n");
+ print_factory("}\n");
+}
+
+void write_factory(const statement_list_t *stmts)
+{
+
+ if (!do_factory)
+ return;
+
+ if (!stmts)
+ return;
+
+ init_factory();
+ if (!factory)
+ return;
+
+ write_class_array(stmts);
+ write_factory_methods();
+
+ fclose(factory);
+}
diff --git a/tools/widl/parser.y b/tools/widl/parser.y
index d979394182..ed46b216d0 100644
--- a/tools/widl/parser.y
+++ b/tools/widl/parser.y
@@ -334,6 +334,7 @@ input: gbl_statements m_acf { fix_incomplete();
write_typelib_regscript($1);
write_dlldata($1);
write_local_stubs($1);
+ write_factory($1);
}
;
diff --git a/tools/widl/widl.c b/tools/widl/widl.c
index 410efb4c4c..6e10a5d092 100644
--- a/tools/widl/widl.c
+++ b/tools/widl/widl.c
@@ -58,6 +58,7 @@ static const char usage[] =
" -d n Set debug level to 'n'\n"
" -D id[=val] Define preprocessor identifier id=val\n"
" -E Preprocess only\n"
+" -f Generate class factory\n"
" --help Display this help and exit\n"
" -h Generate headers\n"
" -H file Name of header file (default is infile.h)\n"
@@ -111,6 +112,7 @@ int do_server = 0;
int do_regscript = 0;
int do_idfile = 0;
int do_dlldata = 0;
+int do_factory = 0;
static int no_preprocess = 0;
int old_names = 0;
int do_win32 = 1;
@@ -137,6 +139,7 @@ char *server_name;
char *server_token;
char *regscript_name;
char *regscript_token;
+char *factory_name;
static char *idfile_name;
char *temp_name;
const char *prefix_client = "";
@@ -172,7 +175,7 @@ enum {
};
static const char short_options[] =
- "b:cC:d:D:EhH:I:m:No:O:pP:rsS:tT:uU:VW";
+ "b:cC:d:D:EfhH:I:m:No:O:pP:rsS:tT:uU:VW";
static const struct option long_options[] = {
{ "acf", 1, NULL, ACF_OPTION },
{ "app_config", 0, NULL, APP_CONFIG_OPTION },
@@ -319,6 +322,7 @@ static void set_everything(int x)
do_regscript = x;
do_idfile = x;
do_dlldata = x;
+ do_factory = x;
}
void start_cplusplus_guard(FILE *fp)
@@ -647,6 +651,10 @@ int main(int argc,char *argv[])
do_everything = 0;
preprocess_only = 1;
break;
+ case 'f':
+ do_everything = 0;
+ do_factory = 1;
+ break;
case 'h':
do_everything = 0;
do_header = 1;
@@ -725,7 +733,7 @@ int main(int argc,char *argv[])
/* if nothing specified, try to guess output type from the output file name */
if (output_name && do_everything && !do_header && !do_typelib && !do_proxies &&
- !do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata)
+ !do_client && !do_server && !do_regscript && !do_idfile && !do_dlldata && !do_factory)
{
do_everything = 0;
if (strendswith( output_name, ".h" )) do_header = 1;
@@ -737,6 +745,7 @@ int main(int argc,char *argv[])
else if (strendswith( output_name, "_r.res" )) do_regscript = 1;
else if (strendswith( output_name, "_t.res" )) do_typelib = 1;
else if (strendswith( output_name, "dlldata.c" )) do_dlldata = 1;
+ else if (strendswith( output_name, "_f.c" )) do_factory = 1;
else do_everything = 1;
}
@@ -747,7 +756,7 @@ int main(int argc,char *argv[])
if (!output_name) output_name = dup_basename(input_name, ".idl");
if (do_header + do_typelib + do_proxies + do_client +
- do_server + do_regscript + do_idfile + do_dlldata == 1)
+ do_server + do_regscript + do_idfile + do_dlldata + do_factory == 1)
{
if (do_header) header_name = output_name;
else if (do_typelib) typelib_name = output_name;
@@ -757,6 +766,7 @@ int main(int argc,char *argv[])
else if (do_regscript) regscript_name = output_name;
else if (do_idfile) idfile_name = output_name;
else if (do_dlldata) dlldata_name = output_name;
+ else if (do_factory) factory_name = output_name;
}
if (!dlldata_name && do_dlldata)
@@ -832,6 +842,11 @@ int main(int argc,char *argv[])
strcat(idfile_name, "_i.c");
}
+ if (!factory_name && do_factory) {
+ factory_name = dup_basename(input_name, ".idl");
+ strcat(factory_name, "_f.c");
+ }
+
if (do_proxies) proxy_token = dup_basename_token(proxy_name,"_p.c");
if (do_client) client_token = dup_basename_token(client_name,"_c.c");
if (do_server) server_token = dup_basename_token(server_name,"_s.c");
@@ -922,4 +937,6 @@ static void rm_tempfile(void)
unlink(proxy_name);
if (do_typelib)
unlink(typelib_name);
+ if (do_factory)
+ unlink(factory_name);
}
diff --git a/tools/widl/widl.h b/tools/widl/widl.h
index 118e2245c2..759a7b818e 100644
--- a/tools/widl/widl.h
+++ b/tools/widl/widl.h
@@ -44,6 +44,7 @@ extern int do_server;
extern int do_regscript;
extern int do_idfile;
extern int do_dlldata;
+extern int do_factory;
extern int old_names;
extern int do_win32;
extern int do_win64;
@@ -66,6 +67,7 @@ extern char *client_name;
extern char *client_token;
extern char *server_name;
extern char *server_token;
+extern char *factory_name;
extern char *regscript_name;
extern char *regscript_token;
extern const char *prefix_client;
@@ -94,6 +96,7 @@ extern void write_typelib_regscript(const statement_list_t *stmts);
extern void output_typelib_regscript( const typelib_t *typelib );
extern void write_local_stubs(const statement_list_t *stmts);
extern void write_dlldata(const statement_list_t *stmts);
+extern void write_factory(const statement_list_t *stmts);
extern void start_cplusplus_guard(FILE *fp);
extern void end_cplusplus_guard(FILE *fp);
--
2.19.1
2
1
[v4 PATCH 1/4] comctl32/tests: Add more Listbox tests for ownerdraw styles.
by Nikolay Sivov 10 Nov '18
by Nikolay Sivov 10 Nov '18
10 Nov '18
From: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/comctl32/tests/listbox.c | 50 +++++++++++++++++++++++++++++++++++
1 file changed, 50 insertions(+)
diff --git a/dlls/comctl32/tests/listbox.c b/dlls/comctl32/tests/listbox.c
index d4bb2cc2a8..c118047b4f 100644
--- a/dlls/comctl32/tests/listbox.c
+++ b/dlls/comctl32/tests/listbox.c
@@ -433,6 +433,35 @@ static void test_ownerdraw(void)
ok(rc.top < 0, "rc.top is not negative (%d)\n", rc.top);
DestroyWindow(hLB);
+
+ /* Both FIXED and VARIABLE, FIXED should override VARIABLE. */
+ hLB = CreateWindowA(WC_LISTBOXA, "TestList", LBS_OWNERDRAWFIXED | LBS_OWNERDRAWVARIABLE, 0, 0, 100, 100,
+ NULL, NULL, NULL, 0);
+ ok(hLB != NULL, "last error 0x%08x\n", GetLastError());
+
+ ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
+ ok(ret == 0, "Unexpected return value %d.\n", ret);
+ ret = SendMessageA(hLB, LB_INSERTSTRING, -1, 0);
+ ok(ret == 1, "Unexpected return value %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 0, 13);
+ ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
+ ok(ret == 13, "Unexpected item height %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_SETITEMHEIGHT, 1, 42);
+ ok(ret == LB_OKAY, "Failed to set item height, %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 0, 0);
+todo_wine
+ ok(ret == 42, "Unexpected item height %d.\n", ret);
+
+ ret = SendMessageA(hLB, LB_GETITEMHEIGHT, 1, 0);
+ ok(ret == 42, "Unexpected item height %d.\n", ret);
+
+ DestroyWindow (hLB);
+
DestroyWindow(parent);
}
@@ -1737,7 +1766,13 @@ static void test_listbox_dlgdir(void)
static void test_set_count( void )
{
+ static const DWORD styles[] =
+ {
+ LBS_OWNERDRAWFIXED,
+ LBS_HASSTRINGS,
+ };
HWND parent, listbox;
+ unsigned int i;
LONG ret;
RECT r;
@@ -1767,6 +1802,21 @@ static void test_set_count( void )
ok( !IsRectEmpty( &r ), "got empty rect\n");
DestroyWindow( listbox );
+
+ for (i = 0; i < ARRAY_SIZE(styles); ++i)
+ {
+ listbox = create_listbox( styles[i] | WS_CHILD | WS_VISIBLE, parent );
+
+ SetLastError( 0xdeadbeef );
+ ret = SendMessageA( listbox, LB_SETCOUNT, 100, 0 );
+ todo_wine_if(i == 0)
+ ok( ret == LB_ERR, "expected %d, got %d\n", LB_ERR, ret );
+ todo_wine_if(i == 1)
+ ok( GetLastError() == 0xdeadbeef, "Unexpected error %d.\n", GetLastError() );
+
+ DestroyWindow( listbox );
+ }
+
DestroyWindow( parent );
}
--
2.19.1
2
6
[PATCH] ntdll: Call system hook in LdrResolveDelayLoadedAPI when dll hook is missing (try 2)
by André Hentschel 10 Nov '18
by André Hentschel 10 Nov '18
10 Nov '18
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=46089
Signed-off-by: Andr� Hentschel <nerv(a)dawncrow.de>
---
try 2: Fixed bad assumption about the purpose of hook return values
dlls/kernel32/tests/loader.c | 53 ++++++++++++++++++++++++++++++++----
dlls/ntdll/loader.c | 18 ++++++++++--
include/delayloadhandler.h | 1 +
3 files changed, 64 insertions(+), 8 deletions(-)
diff --git a/dlls/kernel32/tests/loader.c b/dlls/kernel32/tests/loader.c
index bc88c5f6cf..01c7cfa8a9 100644
--- a/dlls/kernel32/tests/loader.c
+++ b/dlls/kernel32/tests/loader.c
@@ -48,7 +48,7 @@ struct PROCESS_BASIC_INFORMATION_PRIVATE
};
static LONG *child_failures;
-static WORD cb_count;
+static WORD cb_count, cb_count_sys;
static DWORD page_size;
static BOOL is_win64 = sizeof(void *) > sizeof(int);
static BOOL is_wow64;
@@ -70,7 +70,8 @@ static NTSTATUS (WINAPI *pLdrUnlockLoaderLock)(ULONG, ULONG_PTR);
static void (WINAPI *pRtlAcquirePebLock)(void);
static void (WINAPI *pRtlReleasePebLock)(void);
static PVOID (WINAPI *pResolveDelayLoadedAPI)(PVOID, PCIMAGE_DELAYLOAD_DESCRIPTOR,
- PDELAYLOAD_FAILURE_DLL_CALLBACK, PVOID,
+ PDELAYLOAD_FAILURE_DLL_CALLBACK,
+ PDELAYLOAD_FAILURE_SYSTEM_ROUTINE,
PIMAGE_THUNK_DATA ThunkAddress,ULONG);
static PVOID (WINAPI *pRtlImageDirectoryEntryToData)(HMODULE,BOOL,WORD,ULONG *);
static DWORD (WINAPI *pFlsAlloc)(PFLS_CALLBACK_FUNCTION);
@@ -3339,6 +3340,14 @@ static PVOID WINAPI failuredllhook(ULONG ul, DELAYLOAD_INFO* pd)
return (void*)0xdeadbeef;
}
+static PVOID WINAPI failuresyshook(const char *dll, const char *function)
+{
+ ok(!strcmp(dll, "secur32.dll"), "wrong dll: %s\n", dll);
+ ok(!((ULONG_PTR)function >> 16), "expected ordinal, got %p\n", function);
+ cb_count_sys++;
+ return (void*)0x12345678;
+}
+
static void test_ResolveDelayLoadedAPI(void)
{
static const char test_dll[] = "secur32.dll";
@@ -3573,8 +3582,9 @@ static void test_ResolveDelayLoadedAPI(void)
load = (void *)GetProcAddress(htarget, (char*)iibn->Name);
}
- cb_count = 0;
- ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, NULL, &itda[i], 0);
+ /* test without failure dll callback */
+ cb_count = cb_count_sys = 0;
+ ret = pResolveDelayLoadedAPI(hlib, delaydir, NULL, failuresyshook, &itda[i], 0);
if (td[i].succeeds)
{
ok(ret != NULL, "Test %u: ResolveDelayLoadedAPI failed\n", i);
@@ -3582,11 +3592,42 @@ static void test_ResolveDelayLoadedAPI(void)
ok(ret == (void*)itda[i].u1.AddressOfData, "Test %u: expected %p, got %p\n",
i, ret, (void*)itda[i].u1.AddressOfData);
ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
+ ok(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys);
}
else
{
- ok(ret == (void*)0xdeadbeef, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret);
- ok(cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
+ ok(ret == (void*)0x12345678, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret);
+ ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
+ ok(cb_count_sys == 1, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys);
+ }
+
+ /* test with failure dll callback */
+ cb_count = cb_count_sys = 0;
+ ret = pResolveDelayLoadedAPI(hlib, delaydir, failuredllhook, failuresyshook, &itda[i], 0);
+ if (td[i].succeeds)
+ {
+ ok(ret != NULL, "Test %u: ResolveDelayLoadedAPI failed\n", i);
+ ok(ret == load, "Test %u: expected %p, got %p\n", i, load, ret);
+ ok(ret == (void*)itda[i].u1.AddressOfData, "Test %u: expected %p, got %p\n",
+ i, ret, (void*)itda[i].u1.AddressOfData);
+ ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
+ ok(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys);
+ }
+ else
+ {
+ if (ret == (void*)0x12345678)
+ {
+ /* Win10+ sometimes buffers the address of the stub function */
+ ok(!cb_count, "Test %u: Wrong callback count: %d\n", i, cb_count);
+ ok(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys);
+ }
+ else if (ret == (void*)0xdeadbeef)
+ {
+ ok(cb_count == 1, "Test %u: Wrong callback count: %d\n", i, cb_count);
+ ok(!cb_count_sys, "Test %u: Wrong sys callback count: %d\n", i, cb_count_sys);
+ }
+ else
+ ok(0, "Test %u: ResolveDelayLoadedAPI succeeded with %p\n", i, ret);
}
}
delaydir++;
diff --git a/dlls/ntdll/loader.c b/dlls/ntdll/loader.c
index c5e8d0d7c1..ce1b1f28ec 100644
--- a/dlls/ntdll/loader.c
+++ b/dlls/ntdll/loader.c
@@ -2934,7 +2934,8 @@ BOOLEAN WINAPI RtlDllShutdownInProgress(void)
* LdrResolveDelayLoadedAPI (NTDLL.@)
*/
void* WINAPI LdrResolveDelayLoadedAPI( void* base, const IMAGE_DELAYLOAD_DESCRIPTOR* desc,
- PDELAYLOAD_FAILURE_DLL_CALLBACK dllhook, void* syshook,
+ PDELAYLOAD_FAILURE_DLL_CALLBACK dllhook,
+ PDELAYLOAD_FAILURE_SYSTEM_ROUTINE syshook,
IMAGE_THUNK_DATA* addr, ULONG flags )
{
IMAGE_THUNK_DATA *pIAT, *pINT;
@@ -2992,7 +2993,20 @@ fail:
delayinfo.TargetModuleBase = *phmod;
delayinfo.Unused = NULL;
delayinfo.LastError = nts;
- return dllhook(4, &delayinfo);
+
+ if (dllhook)
+ return dllhook(4, &delayinfo);
+
+ if (IMAGE_SNAP_BY_ORDINAL(pINT[id].u1.Ordinal))
+ {
+ DWORD_PTR ord = LOWORD(pINT[id].u1.Ordinal);
+ return syshook(name, (char*)ord);
+ }
+ else
+ {
+ const IMAGE_IMPORT_BY_NAME* iibn = get_rva(base, pINT[id].u1.AddressOfData);
+ return syshook(name, (char*)iibn->Name);
+ }
}
/******************************************************************
diff --git a/include/delayloadhandler.h b/include/delayloadhandler.h
index 06b658990c..e8336111ff 100644
--- a/include/delayloadhandler.h
+++ b/include/delayloadhandler.h
@@ -47,6 +47,7 @@ typedef struct _DELAYLOAD_INFO
} DELAYLOAD_INFO, *PDELAYLOAD_INFO;
typedef PVOID (WINAPI *PDELAYLOAD_FAILURE_DLL_CALLBACK)(ULONG, PDELAYLOAD_INFO);
+typedef PVOID (WINAPI *PDELAYLOAD_FAILURE_SYSTEM_ROUTINE)(LPCSTR, LPCSTR);
#ifdef __cplusplus
}
--
2.17.1
2
1
The same "struct message" cannot be reused easily, revert to old behavior and
allocate a new one.
This fixes keyboard input on e.g. Witcher 3, which would just hang upon
pressing the first key.
Fixes: 383cf211 ("server: Add a helper function to allocate a hardware message.")
Signed-off-by: Andre Heider <a.heider(a)gmail.com>
---
server/queue.c | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/server/queue.c b/server/queue.c
index 9dfbd1e294..545991b99c 100644
--- a/server/queue.c
+++ b/server/queue.c
@@ -1775,11 +1775,11 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
break;
}
- if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
- msg_data = msg->data;
-
if ((device = current->process->rawinput_kbd))
{
+ if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
+ msg_data = msg->data;
+
msg->win = device->target;
msg->msg = WM_INPUT;
msg->wparam = RIM_INPUT;
@@ -1793,6 +1793,9 @@ static int queue_keyboard_message( struct desktop *desktop, user_handle_t win, c
queue_hardware_message( desktop, msg, 0 );
}
+ if (!(msg = alloc_hardware_message( input->kbd.info, source, time ))) return 0;
+ msg_data = msg->data;
+
msg->win = get_user_full_handle( win );
msg->msg = message_code;
msg->lparam = (input->kbd.scan << 16) | 1u; /* repeat count */
--
2.19.1
1
0