Wine-Devel
By thread
wine-devel@list.winehq.org
By month
Messages by month
- ----- 2026 -----
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2025 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2010 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2009 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2008 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2007 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2006 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2005 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2004 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2003 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2002 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2001 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
September 2018
- 70 participants
- 1549 messages
[PATCH v6 4/6] shell32/autocomplete: Simplify a calculation
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/shell32/autocomplete.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index c7c6240..547267d 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -217,7 +217,7 @@ static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_
/* It seems that Windows XP displays 7 lines at most
and otherwise displays a vertical scroll bar */
SetWindowPos(ac->hwndListBox, HWND_TOP,
- r.left, r.bottom + 1, r.right - r.left, min(height * 7, height*(cpt+1)),
+ r.left, r.bottom + 1, r.right - r.left, height * min(cpt + 1, 7),
SWP_SHOWWINDOW );
}
else
--
1.9.1
Sept. 14, 2018
[PATCH v6 3/6] shell32/autocomplete: Avoid another buffer overflow and handle arbitrary sizes for the auto-append string
by Gabriel Ivăncescu
The previous code caps the auto-append text at 255 characters, which can be
easily exploited. It's also less efficient as it scans the string multiple
times.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
dlls/shell32/autocomplete.c | 29 +++++++++++++++++++++++------
1 file changed, 23 insertions(+), 6 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index b9ec228..c7c6240 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -126,6 +126,28 @@ static size_t format_quick_complete(WCHAR *dst, const WCHAR *qc, const WCHAR *st
return dst - base;
}
+static void autoappend_str(IAutoCompleteImpl *ac, WCHAR *text, UINT len, WCHAR *str, HWND hwnd)
+{
+ WCHAR *tmp;
+ size_t size;
+
+ /* The character capitalization can be different,
+ so merge text and str into a new string */
+ size = len + strlenW(&str[len]) + 1;
+
+ if ((tmp = heap_alloc(size * sizeof(*tmp))))
+ {
+ memcpy(tmp, text, len * sizeof(*tmp));
+ memcpy(&tmp[len], &str[len], (size - len) * sizeof(*tmp));
+ }
+ else tmp = str;
+
+ SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)tmp);
+ SendMessageW(hwnd, EM_SETSEL, len, size - 1);
+ if (tmp != str)
+ heap_free(tmp);
+}
+
static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_flag flag)
{
HRESULT hr;
@@ -166,12 +188,7 @@ static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_
{
if (cpt == 0 && flag == autoappend_flag_yes)
{
- WCHAR buffW[255];
-
- strcpyW(buffW, text);
- strcatW(buffW, &strs[len]);
- SetWindowTextW(hwnd, buffW);
- SendMessageW(hwnd, EM_SETSEL, len, strlenW(strs));
+ autoappend_str(ac, text, len, strs, hwnd);
if (!(ac->options & ACO_AUTOSUGGEST))
{
CoTaskMemFree(strs);
--
1.9.1
Sept. 14, 2018
[PATCH v6 2/6] shell32/autocomplete: Redesign the window proc to trigger on key presses instead of key release
by Gabriel Ivăncescu
AutoComplete currently shows up when the user releases a key, which is
wrong. Windows does it when the user presses a key, so use both WM_KEYDOWN
and WM_CHAR and redesign it so that it matches Windows behavior.
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
v6: Use an enum instead of BOOL for the autoappend flag.
dlls/shell32/autocomplete.c | 116 +++++++++++++++++++++++++-------------------
1 file changed, 66 insertions(+), 50 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index ebbb9ee..b9ec228 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -79,6 +79,13 @@ typedef struct
AUTOCOMPLETEOPTIONS options;
} IAutoCompleteImpl;
+enum autoappend_flag
+{
+ autoappend_flag_yes,
+ autoappend_flag_no,
+ autoappend_flag_displayempty
+};
+
static const WCHAR autocomplete_propertyW[] = {'W','i','n','e',' ','A','u','t','o',
'c','o','m','p','l','e','t','e',' ',
'c','o','n','t','r','o','l',0};
@@ -119,10 +126,25 @@ static size_t format_quick_complete(WCHAR *dst, const WCHAR *qc, const WCHAR *st
return dst - base;
}
-static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND hwnd, BOOL displayall)
+static void autocomplete_text(IAutoCompleteImpl *ac, HWND hwnd, enum autoappend_flag flag)
{
HRESULT hr;
- UINT cpt;
+ WCHAR *text;
+ UINT cpt, size, len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+
+ if (flag != autoappend_flag_displayempty && len == 0)
+ {
+ if (ac->options & ACO_AUTOSUGGEST)
+ ShowWindow(ac->hwndListBox, SW_HIDE);
+ return;
+ }
+
+ size = len + 1;
+ if (!(text = heap_alloc(size * sizeof(WCHAR))))
+ return;
+ len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)text);
+ if (len + 1 != size)
+ text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0);
@@ -130,9 +152,6 @@ static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND
heap_free(ac->txtbackup);
ac->txtbackup = text;
- if (!displayall && !len)
- return;
-
IEnumString_Reset(ac->enumstr);
for(cpt = 0;;)
{
@@ -145,7 +164,7 @@ static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND
if (!strncmpiW(text, strs, len))
{
- if (cpt == 0 && (ac->options & ACO_AUTOAPPEND))
+ if (cpt == 0 && flag == autoappend_flag_yes)
{
WCHAR buffW[255];
@@ -200,27 +219,23 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
/*
Helper for ACEditSubclassProc
*/
-static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT uMsg,
- WPARAM wParam, LPARAM lParam)
+static LRESULT ACEditSubclassProc_KeyDown(IAutoCompleteImpl *ac, HWND hwnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
{
- WCHAR *text;
- UINT len, size;
- BOOL displayall = FALSE;
-
- len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
- size = len + 1;
- if (!(text = heap_alloc(size * sizeof(WCHAR))))
- return 0;
- len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)text);
-
switch(wParam)
{
case VK_RETURN:
/* If quickComplete is set and control is pressed, replace the string */
if (ac->quickComplete && (GetKeyState(VK_CONTROL) & 0x8000))
{
- WCHAR *buf;
- size_t sz = strlenW(ac->quickComplete) + 1 + len;
+ WCHAR *text, *buf;
+ size_t sz;
+ UINT len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+ if (!(text = heap_alloc((len + 1) * sizeof(WCHAR))))
+ return 0;
+ len = SendMessageW(hwnd, WM_GETTEXT, len + 1, (LPARAM)text);
+ sz = strlenW(ac->quickComplete) + 1 + len;
+
if ((buf = heap_alloc(sz * sizeof(WCHAR))))
{
len = format_quick_complete(buf, ac->quickComplete, text, len);
@@ -228,16 +243,16 @@ static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT u
SendMessageW(hwnd, EM_SETSEL, 0, len);
heap_free(buf);
}
+
+ if (ac->options & ACO_AUTOSUGGEST)
+ ShowWindow(ac->hwndListBox, SW_HIDE);
+ heap_free(text);
+ return 0;
}
if (ac->options & ACO_AUTOSUGGEST)
ShowWindow(ac->hwndListBox, SW_HIDE);
- heap_free(text);
- return 0;
- case VK_LEFT:
- case VK_RIGHT:
- heap_free(text);
- return 0;
+ break;
case VK_UP:
case VK_DOWN:
/* Two cases here:
@@ -245,19 +260,20 @@ static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT u
set, display it with all the entries, without selecting any
- if the listbox is visible, change the selection
*/
- if ( (ac->options & (ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST))
- && (!IsWindowVisible(ac->hwndListBox) && (! *text)) )
+ if (!(ac->options & ACO_AUTOSUGGEST))
+ break;
+
+ if (!IsWindowVisible(ac->hwndListBox))
{
- /* We must display all the entries */
- displayall = TRUE;
+ if (ac->options & ACO_UPDOWNKEYDROPSLIST)
+ {
+ autocomplete_text(ac, hwnd, autoappend_flag_displayempty);
+ return 0;
+ }
}
else
{
INT count, sel;
- heap_free(text);
- if (!IsWindowVisible(ac->hwndListBox))
- return 0;
-
count = SendMessageW(ac->hwndListBox, LB_GETCOUNT, 0, 0);
/* Change the selection */
@@ -290,22 +306,14 @@ static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT u
return 0;
}
break;
- case VK_BACK:
case VK_DELETE:
- if ((! *text) && (ac->options & ACO_AUTOSUGGEST))
- {
- heap_free(text);
- ShowWindow(ac->hwndListBox, SW_HIDE);
- return CallWindowProcW(ac->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
- }
- break;
+ {
+ LRESULT ret = CallWindowProcW(ac->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
+ autocomplete_text(ac, hwnd, autoappend_flag_no);
+ return ret;
+ }
}
-
- if (len + 1 != size)
- text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
-
- autocomplete_text(ac, text, len, hwnd, displayall);
- return 0;
+ return CallWindowProcW(ac->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
}
/*
@@ -314,6 +322,7 @@ static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT u
static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
IAutoCompleteImpl *This = GetPropW(hwnd, autocomplete_propertyW);
+ LRESULT ret;
if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
@@ -329,8 +338,15 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
ShowWindow(This->hwndListBox, SW_HIDE);
}
return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
- case WM_KEYUP:
- return ACEditSubclassProc_KeyUp(This, hwnd, uMsg, wParam, lParam);
+ case WM_KEYDOWN:
+ return ACEditSubclassProc_KeyDown(This, hwnd, uMsg, wParam, lParam);
+ case WM_CHAR:
+ case WM_UNICHAR:
+ ret = CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
+ autocomplete_text(This, hwnd, (This->options & ACO_AUTOAPPEND) &&
+ (wParam >= ' ' || wParam == 0x16 /* ^V (paste) */)
+ ? autoappend_flag_yes : autoappend_flag_no);
+ return ret;
case WM_DESTROY:
{
WNDPROC proc = This->wpOrigEditProc;
--
1.9.1
Sept. 14, 2018
[PATCH v6 1/6] shell32/autocomplete: Move the autocomplete processing and WM_KEYUP to separate functions
by Gabriel Ivăncescu
Signed-off-by: Gabriel Ivăncescu <gabrielopcode(a)gmail.com>
---
v6: Also move WM_KEYUP to a separate function.
dlls/shell32/autocomplete.c | 336 ++++++++++++++++++++++++--------------------
1 file changed, 182 insertions(+), 154 deletions(-)
diff --git a/dlls/shell32/autocomplete.c b/dlls/shell32/autocomplete.c
index 9f35ff7..ebbb9ee 100644
--- a/dlls/shell32/autocomplete.c
+++ b/dlls/shell32/autocomplete.c
@@ -119,6 +119,76 @@ static size_t format_quick_complete(WCHAR *dst, const WCHAR *qc, const WCHAR *st
return dst - base;
}
+static void autocomplete_text(IAutoCompleteImpl *ac, WCHAR *text, UINT len, HWND hwnd, BOOL displayall)
+{
+ HRESULT hr;
+ UINT cpt;
+
+ SendMessageW(ac->hwndListBox, LB_RESETCONTENT, 0, 0);
+
+ /* Set txtbackup to point to text itself (which must not be released) */
+ heap_free(ac->txtbackup);
+ ac->txtbackup = text;
+
+ if (!displayall && !len)
+ return;
+
+ IEnumString_Reset(ac->enumstr);
+ for(cpt = 0;;)
+ {
+ LPOLESTR strs = NULL;
+ ULONG fetched;
+
+ hr = IEnumString_Next(ac->enumstr, 1, &strs, &fetched);
+ if (hr != S_OK)
+ break;
+
+ if (!strncmpiW(text, strs, len))
+ {
+ if (cpt == 0 && (ac->options & ACO_AUTOAPPEND))
+ {
+ WCHAR buffW[255];
+
+ strcpyW(buffW, text);
+ strcatW(buffW, &strs[len]);
+ SetWindowTextW(hwnd, buffW);
+ SendMessageW(hwnd, EM_SETSEL, len, strlenW(strs));
+ if (!(ac->options & ACO_AUTOSUGGEST))
+ {
+ CoTaskMemFree(strs);
+ break;
+ }
+ }
+
+ if (ac->options & ACO_AUTOSUGGEST)
+ SendMessageW(ac->hwndListBox, LB_ADDSTRING, 0, (LPARAM)strs);
+
+ cpt++;
+ }
+
+ CoTaskMemFree(strs);
+ }
+
+ if (ac->options & ACO_AUTOSUGGEST)
+ {
+ if (cpt)
+ {
+ RECT r;
+ UINT height = SendMessageW(ac->hwndListBox, LB_GETITEMHEIGHT, 0, 0);
+ SendMessageW(ac->hwndListBox, LB_CARETOFF, 0, 0);
+ GetWindowRect(hwnd, &r);
+ SetParent(ac->hwndListBox, HWND_DESKTOP);
+ /* It seems that Windows XP displays 7 lines at most
+ and otherwise displays a vertical scroll bar */
+ SetWindowPos(ac->hwndListBox, HWND_TOP,
+ r.left, r.bottom + 1, r.right - r.left, min(height * 7, height*(cpt+1)),
+ SWP_SHOWWINDOW );
+ }
+ else
+ ShowWindow(ac->hwndListBox, SW_HIDE);
+ }
+}
+
static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
{
ac->hwndEdit = NULL;
@@ -128,17 +198,122 @@ static void destroy_autocomplete_object(IAutoCompleteImpl *ac)
}
/*
+ Helper for ACEditSubclassProc
+*/
+static LRESULT ACEditSubclassProc_KeyUp(IAutoCompleteImpl *ac, HWND hwnd, UINT uMsg,
+ WPARAM wParam, LPARAM lParam)
+{
+ WCHAR *text;
+ UINT len, size;
+ BOOL displayall = FALSE;
+
+ len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
+ size = len + 1;
+ if (!(text = heap_alloc(size * sizeof(WCHAR))))
+ return 0;
+ len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)text);
+
+ switch(wParam)
+ {
+ case VK_RETURN:
+ /* If quickComplete is set and control is pressed, replace the string */
+ if (ac->quickComplete && (GetKeyState(VK_CONTROL) & 0x8000))
+ {
+ WCHAR *buf;
+ size_t sz = strlenW(ac->quickComplete) + 1 + len;
+ if ((buf = heap_alloc(sz * sizeof(WCHAR))))
+ {
+ len = format_quick_complete(buf, ac->quickComplete, text, len);
+ SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)buf);
+ SendMessageW(hwnd, EM_SETSEL, 0, len);
+ heap_free(buf);
+ }
+ }
+
+ if (ac->options & ACO_AUTOSUGGEST)
+ ShowWindow(ac->hwndListBox, SW_HIDE);
+ heap_free(text);
+ return 0;
+ case VK_LEFT:
+ case VK_RIGHT:
+ heap_free(text);
+ return 0;
+ case VK_UP:
+ case VK_DOWN:
+ /* Two cases here:
+ - if the listbox is not visible and ACO_UPDOWNKEYDROPSLIST is
+ set, display it with all the entries, without selecting any
+ - if the listbox is visible, change the selection
+ */
+ if ( (ac->options & (ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST))
+ && (!IsWindowVisible(ac->hwndListBox) && (! *text)) )
+ {
+ /* We must display all the entries */
+ displayall = TRUE;
+ }
+ else
+ {
+ INT count, sel;
+ heap_free(text);
+ if (!IsWindowVisible(ac->hwndListBox))
+ return 0;
+
+ count = SendMessageW(ac->hwndListBox, LB_GETCOUNT, 0, 0);
+
+ /* Change the selection */
+ sel = SendMessageW(ac->hwndListBox, LB_GETCURSEL, 0, 0);
+ if (wParam == VK_UP)
+ sel = ((sel - 1) < 0) ? count - 1 : sel - 1;
+ else
+ sel = ((sel + 1) >= count) ? -1 : sel + 1;
+ SendMessageW(ac->hwndListBox, LB_SETCURSEL, sel, 0);
+ if (sel >= 0)
+ {
+ WCHAR *msg;
+ UINT len;
+
+ len = SendMessageW(ac->hwndListBox, LB_GETTEXTLEN, sel, 0);
+ if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR))))
+ return 0;
+ len = SendMessageW(ac->hwndListBox, LB_GETTEXT, sel, (LPARAM)msg);
+ SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)msg);
+ SendMessageW(hwnd, EM_SETSEL, len, len);
+ heap_free(msg);
+ }
+ else
+ {
+ UINT len;
+ SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)ac->txtbackup);
+ len = strlenW(ac->txtbackup);
+ SendMessageW(hwnd, EM_SETSEL, len, len);
+ }
+ return 0;
+ }
+ break;
+ case VK_BACK:
+ case VK_DELETE:
+ if ((! *text) && (ac->options & ACO_AUTOSUGGEST))
+ {
+ heap_free(text);
+ ShowWindow(ac->hwndListBox, SW_HIDE);
+ return CallWindowProcW(ac->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
+ }
+ break;
+ }
+
+ if (len + 1 != size)
+ text = heap_realloc(text, (len + 1) * sizeof(WCHAR));
+
+ autocomplete_text(ac, text, len, hwnd, displayall);
+ return 0;
+}
+
+/*
Window procedure for autocompletion
*/
static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
{
IAutoCompleteImpl *This = GetPropW(hwnd, autocomplete_propertyW);
- HRESULT hr;
- WCHAR *hwndText;
- UINT len, size, cpt;
- RECT r;
- BOOL displayall = FALSE;
- int height, sel;
if (!This->enabled) return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
@@ -155,154 +330,7 @@ static LRESULT APIENTRY ACEditSubclassProc(HWND hwnd, UINT uMsg, WPARAM wParam,
}
return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
case WM_KEYUP:
- len = SendMessageW(hwnd, WM_GETTEXTLENGTH, 0, 0);
- size = len + 1;
- if (!(hwndText = heap_alloc(size * sizeof(WCHAR))))
- return 0;
- len = SendMessageW(hwnd, WM_GETTEXT, size, (LPARAM)hwndText);
-
- switch(wParam) {
- case VK_RETURN:
- /* If quickComplete is set and control is pressed, replace the string */
- if (This->quickComplete && (GetKeyState(VK_CONTROL) & 0x8000))
- {
- WCHAR *buf;
- size_t sz = strlenW(This->quickComplete) + 1 + len;
- if ((buf = heap_alloc(sz * sizeof(WCHAR))))
- {
- len = format_quick_complete(buf, This->quickComplete, hwndText, len);
- SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)buf);
- SendMessageW(hwnd, EM_SETSEL, 0, len);
- heap_free(buf);
- }
- }
-
- if (This->options & ACO_AUTOSUGGEST)
- ShowWindow(This->hwndListBox, SW_HIDE);
- heap_free(hwndText);
- return 0;
- case VK_LEFT:
- case VK_RIGHT:
- heap_free(hwndText);
- return 0;
- case VK_UP:
- case VK_DOWN:
- /* Two cases here :
- - if the listbox is not visible, displays it
- with all the entries if the style ACO_UPDOWNKEYDROPSLIST
- is present but does not select anything.
- - if the listbox is visible, change the selection
- */
- if ( (This->options & (ACO_AUTOSUGGEST | ACO_UPDOWNKEYDROPSLIST))
- && (!IsWindowVisible(This->hwndListBox) && (! *hwndText)) )
- {
- /* We must display all the entries */
- displayall = TRUE;
- } else {
- heap_free(hwndText);
- if (IsWindowVisible(This->hwndListBox)) {
- int count;
-
- count = SendMessageW(This->hwndListBox, LB_GETCOUNT, 0, 0);
- /* Change the selection */
- sel = SendMessageW(This->hwndListBox, LB_GETCURSEL, 0, 0);
- if (wParam == VK_UP)
- sel = ((sel-1) < 0) ? count-1 : sel-1;
- else
- sel = ((sel+1) >= count) ? -1 : sel+1;
- SendMessageW(This->hwndListBox, LB_SETCURSEL, sel, 0);
- if (sel != -1) {
- WCHAR *msg;
- int len;
-
- len = SendMessageW(This->hwndListBox, LB_GETTEXTLEN, sel, 0);
- if (!(msg = heap_alloc((len + 1) * sizeof(WCHAR))))
- return 0;
- len = SendMessageW(This->hwndListBox, LB_GETTEXT, sel, (LPARAM)msg);
- SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)msg);
- SendMessageW(hwnd, EM_SETSEL, len, len);
- heap_free(msg);
- } else {
- UINT len;
- SendMessageW(hwnd, WM_SETTEXT, 0, (LPARAM)This->txtbackup);
- len = strlenW(This->txtbackup);
- SendMessageW(hwnd, EM_SETSEL, len, len);
- }
- }
- return 0;
- }
- break;
- case VK_BACK:
- case VK_DELETE:
- if ((! *hwndText) && (This->options & ACO_AUTOSUGGEST)) {
- heap_free(hwndText);
- ShowWindow(This->hwndListBox, SW_HIDE);
- return CallWindowProcW(This->wpOrigEditProc, hwnd, uMsg, wParam, lParam);
- }
- break;
- }
-
- if (len + 1 != size)
- hwndText = heap_realloc(hwndText, (len + 1) * sizeof(WCHAR));
-
- SendMessageW(This->hwndListBox, LB_RESETCONTENT, 0, 0);
-
- /* Set txtbackup to point to hwndText itself (which must not be released) */
- heap_free(This->txtbackup);
- This->txtbackup = hwndText;
-
- if (!displayall && !len)
- break;
-
- IEnumString_Reset(This->enumstr);
- for(cpt = 0;;) {
- LPOLESTR strs = NULL;
- ULONG fetched;
-
- hr = IEnumString_Next(This->enumstr, 1, &strs, &fetched);
- if (hr != S_OK)
- break;
-
- if (!strncmpiW(hwndText, strs, len)) {
- if (cpt == 0 && (This->options & ACO_AUTOAPPEND)) {
- WCHAR buffW[255];
-
- strcpyW(buffW, hwndText);
- strcatW(buffW, &strs[len]);
- SetWindowTextW(hwnd, buffW);
- SendMessageW(hwnd, EM_SETSEL, len, strlenW(strs));
- if (!(This->options & ACO_AUTOSUGGEST)) {
- CoTaskMemFree(strs);
- break;
- }
- }
-
- if (This->options & ACO_AUTOSUGGEST)
- SendMessageW(This->hwndListBox, LB_ADDSTRING, 0, (LPARAM)strs);
-
- cpt++;
- }
-
- CoTaskMemFree(strs);
- }
-
- if (This->options & ACO_AUTOSUGGEST) {
- if (cpt) {
- height = SendMessageW(This->hwndListBox, LB_GETITEMHEIGHT, 0, 0);
- SendMessageW(This->hwndListBox, LB_CARETOFF, 0, 0);
- GetWindowRect(hwnd, &r);
- SetParent(This->hwndListBox, HWND_DESKTOP);
- /* It seems that Windows XP displays 7 lines at most
- and otherwise displays a vertical scroll bar */
- SetWindowPos(This->hwndListBox, HWND_TOP,
- r.left, r.bottom + 1, r.right - r.left, min(height * 7, height*(cpt+1)),
- SWP_SHOWWINDOW );
- } else {
- ShowWindow(This->hwndListBox, SW_HIDE);
- }
- }
-
- break;
+ return ACEditSubclassProc_KeyUp(This, hwnd, uMsg, wParam, lParam);
case WM_DESTROY:
{
WNDPROC proc = This->wpOrigEditProc;
--
1.9.1
Sept. 14, 2018
[PATCH 5/5] xmllite/writer: Simplify setting default output encoding.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/xmllite/writer.c | 3 +--
1 file changed, 1 insertion(+), 2 deletions(-)
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c
index a359e35ee9..e9ad941365 100644
--- a/dlls/xmllite/writer.c
+++ b/dlls/xmllite/writer.c
@@ -1846,7 +1846,6 @@ static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_enco
HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IMalloc *imalloc, const WCHAR *encoding,
IXmlWriterOutput **out)
{
- static const WCHAR utf8W[] = {'U','T','F','-','8',0};
xmlwriteroutput *output;
xml_encoding xml_enc;
HRESULT hr;
@@ -1858,7 +1857,7 @@ HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IMalloc *
*out = NULL;
- xml_enc = parse_encoding_name(encoding ? encoding : utf8W, -1);
+ xml_enc = encoding ? parse_encoding_name(encoding, -1) : XmlEncoding_UTF8;
if (SUCCEEDED(hr = create_writer_output(stream, imalloc, xml_enc, encoding, &output)))
*out = &output->IXmlWriterOutput_iface;
--
2.18.0
Sept. 14, 2018
[PATCH 4/5] xmllite/writer: Use internal function to create writer output implicitly.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/xmllite/writer.c | 59 +++++++++++++++++++++++++++----------------
1 file changed, 37 insertions(+), 22 deletions(-)
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c
index f0eac777ca..a359e35ee9 100644
--- a/dlls/xmllite/writer.c
+++ b/dlls/xmllite/writer.c
@@ -148,6 +148,9 @@ static const char *debugstr_writer_prop(XmlWriterProperty prop)
return prop_names[prop];
}
+static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_encoding encoding,
+ const WCHAR *encoding_name, xmlwriteroutput **out);
+
/* writer output memory allocation functions */
static inline void *writeroutput_alloc(xmlwriteroutput *output, size_t len)
{
@@ -735,10 +738,10 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output)
}
if (hr != S_OK || !writeroutput) {
- /* create IXmlWriterOutput basing on supplied interface */
- hr = CreateXmlWriterOutputWithEncodingName(output, This->imalloc, NULL, &writeroutput);
- if (hr != S_OK) return hr;
- This->output = impl_from_IXmlWriterOutput(writeroutput);
+ /* Create output for given stream. */
+ hr = create_writer_output(output, This->imalloc, XmlEncoding_UTF8, NULL, &This->output);
+ if (hr != S_OK)
+ return hr;
}
if (This->output->encoding == XmlEncoding_Unknown)
@@ -1795,12 +1798,12 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc)
}
static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_encoding encoding,
- const WCHAR *encoding_name, IXmlWriterOutput **output)
+ const WCHAR *encoding_name, xmlwriteroutput **out)
{
xmlwriteroutput *writeroutput;
HRESULT hr;
- *output = NULL;
+ *out = NULL;
if (imalloc)
writeroutput = IMalloc_Alloc(imalloc, sizeof(*writeroutput));
@@ -1833,40 +1836,52 @@ static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_enco
IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&writeroutput->output);
- *output = &writeroutput->IXmlWriterOutput_iface;
+ *out = writeroutput;
- TRACE("returning iface %p\n", *output);
+ TRACE("Created writer output %p\n", *out);
return S_OK;
}
-HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream,
- IMalloc *imalloc,
- LPCWSTR encoding,
- IXmlWriterOutput **output)
+HRESULT WINAPI CreateXmlWriterOutputWithEncodingName(IUnknown *stream, IMalloc *imalloc, const WCHAR *encoding,
+ IXmlWriterOutput **out)
{
static const WCHAR utf8W[] = {'U','T','F','-','8',0};
+ xmlwriteroutput *output;
xml_encoding xml_enc;
+ HRESULT hr;
+
+ TRACE("%p %p %s %p\n", stream, imalloc, debugstr_w(encoding), out);
- TRACE("%p %p %s %p\n", stream, imalloc, debugstr_w(encoding), output);
+ if (!stream || !out)
+ return E_INVALIDARG;
- if (!stream || !output) return E_INVALIDARG;
+ *out = NULL;
xml_enc = parse_encoding_name(encoding ? encoding : utf8W, -1);
- return create_writer_output(stream, imalloc, xml_enc, encoding, output);
+ if (SUCCEEDED(hr = create_writer_output(stream, imalloc, xml_enc, encoding, &output)))
+ *out = &output->IXmlWriterOutput_iface;
+
+ return hr;
}
-HRESULT WINAPI CreateXmlWriterOutputWithEncodingCodePage(IUnknown *stream,
- IMalloc *imalloc,
- UINT codepage,
- IXmlWriterOutput **output)
+HRESULT WINAPI CreateXmlWriterOutputWithEncodingCodePage(IUnknown *stream, IMalloc *imalloc, UINT codepage,
+ IXmlWriterOutput **out)
{
+ xmlwriteroutput *output;
xml_encoding xml_enc;
+ HRESULT hr;
- TRACE("%p %p %u %p\n", stream, imalloc, codepage, output);
+ TRACE("%p %p %u %p\n", stream, imalloc, codepage, out);
- if (!stream || !output) return E_INVALIDARG;
+ if (!stream || !out)
+ return E_INVALIDARG;
+
+ *out = NULL;
xml_enc = get_encoding_from_codepage(codepage);
- return create_writer_output(stream, imalloc, xml_enc, NULL, output);
+ if (SUCCEEDED(hr = create_writer_output(stream, imalloc, xml_enc, NULL, &output)))
+ *out = &output->IXmlWriterOutput_iface;
+
+ return hr;
}
--
2.18.0
Sept. 14, 2018
[PATCH 3/5] xmllite/writer: Fix formatted output with interleaving text nodes.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/xmllite/tests/writer.c | 87 +++++++++++++++++++++++++++++++++++++
dlls/xmllite/writer.c | 24 ++++++----
2 files changed, 103 insertions(+), 8 deletions(-)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c
index 42b534f269..7f731be211 100644
--- a/dlls/xmllite/tests/writer.c
+++ b/dlls/xmllite/tests/writer.c
@@ -1981,6 +1981,93 @@ static void test_WriteString(void)
" <b>text</b>\r\n"
"</a>");
+ IStream_Release(stream);
+
+ stream = writer_set_output(writer);
+
+ hr = write_start_element(writer, NULL, "a", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, NULL, "b", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_WriteEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />");
+
+ hr = write_start_element(writer, NULL, "c", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_attribute_string(writer, NULL, "attr", NULL, "value");
+ ok(hr == S_OK, "Failed to write attribute string, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\"");
+
+ hr = write_string(writer, "text");
+ ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\">text");
+
+ hr = IXmlWriter_WriteEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\">text</c>");
+
+ hr = write_start_element(writer, NULL, "d", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_string(writer, "");
+ ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
+
+ hr = IXmlWriter_WriteEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\">text</c>\r\n"
+ " <d></d>");
+
+ hr = IXmlWriter_WriteEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b />\r\n"
+ " <c attr=\"value\">text</c>\r\n"
+ " <d></d>\r\n"
+ "</a>");
+
IXmlWriter_Release(writer);
IStream_Release(stream);
}
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c
index 94e1f2f8a8..f0eac777ca 100644
--- a/dlls/xmllite/writer.c
+++ b/dlls/xmllite/writer.c
@@ -118,6 +118,7 @@ typedef struct _xmlwriter
struct list elements;
DWORD bomwritten : 1;
DWORD starttagopen : 1;
+ DWORD textnode : 1;
} xmlwriter;
static inline xmlwriter *impl_from_IXmlWriter(IXmlWriter *iface)
@@ -626,8 +627,11 @@ static void write_node_indent(xmlwriter *writer)
static const WCHAR crlfW[] = {'\r','\n'};
unsigned int indent_level = writer->indent_level;
- if (!writer->indent)
+ if (!writer->indent || writer->textnode)
+ {
+ writer->textnode = 0;
return;
+ }
/* Do state check to prevent newline inserted after BOM. It is assumed that
state does not change between writing BOM and inserting indentation. */
@@ -635,6 +639,8 @@ static void write_node_indent(xmlwriter *writer)
write_output_buffer(writer->output, crlfW, ARRAY_SIZE(crlfW));
while (indent_level--)
write_output_buffer(writer->output, dblspaceW, ARRAY_SIZE(dblspaceW));
+
+ writer->textnode = 0;
}
static HRESULT WINAPI xmlwriter_QueryInterface(IXmlWriter *iface, REFIID riid, void **ppvObject)
@@ -704,6 +710,7 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output)
IUnknown_Release(&This->output->IXmlWriterOutput_iface);
This->output = NULL;
This->bomwritten = 0;
+ This->textnode = 0;
This->indent_level = 0;
writer_free_element_stack(This);
}
@@ -1281,7 +1288,10 @@ static HRESULT WINAPI xmlwriter_WriteFullEndElement(IXmlWriter *iface)
/* don't force full end tag to the next line */
if (This->state == XmlWriterState_ElemStarted)
+ {
This->state = XmlWriterState_Content;
+ This->textnode = 0;
+ }
else
write_node_indent(This);
@@ -1623,6 +1633,7 @@ static HRESULT WINAPI xmlwriter_WriteString(IXmlWriter *iface, const WCHAR *stri
;
}
+ This->textnode = 1;
write_escaped_string(This, string);
return S_OK;
}
@@ -1761,21 +1772,18 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc)
writer = IMalloc_Alloc(imalloc, sizeof(*writer));
else
writer = heap_alloc(sizeof(*writer));
- if(!writer) return E_OUTOFMEMORY;
+ if (!writer)
+ return E_OUTOFMEMORY;
+
+ memset(writer, 0, sizeof(*writer));
writer->IXmlWriter_iface.lpVtbl = &xmlwriter_vtbl;
writer->ref = 1;
writer->imalloc = imalloc;
if (imalloc) IMalloc_AddRef(imalloc);
- writer->output = NULL;
- writer->indent_level = 0;
- writer->indent = FALSE;
writer->bom = TRUE;
- writer->omitxmldecl = FALSE;
writer->conformance = XmlConformanceLevel_Document;
writer->state = XmlWriterState_Initial;
- writer->bomwritten = 0;
- writer->starttagopen = 0;
list_init(&writer->elements);
hr = IXmlWriter_QueryInterface(&writer->IXmlWriter_iface, riid, obj);
--
2.18.0
Sept. 14, 2018
[PATCH 2/5] xmllite/writer: Fix formatted output for closing tags.
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/xmllite/tests/writer.c | 88 ++++++++++++++++++++++++++++++-------
dlls/xmllite/writer.c | 21 +++++----
2 files changed, 85 insertions(+), 24 deletions(-)
diff --git a/dlls/xmllite/tests/writer.c b/dlls/xmllite/tests/writer.c
index 1710462deb..42b534f269 100644
--- a/dlls/xmllite/tests/writer.c
+++ b/dlls/xmllite/tests/writer.c
@@ -881,6 +881,20 @@ static HRESULT write_element_string(IXmlWriter *writer, const char *prefix, cons
return hr;
}
+static HRESULT write_string(IXmlWriter *writer, const char *str)
+{
+ WCHAR *strW;
+ HRESULT hr;
+
+ strW = strdupAtoW(str);
+
+ hr = IXmlWriter_WriteString(writer, strW);
+
+ heap_free(strW);
+
+ return hr;
+}
+
static void test_WriteStartElement(void)
{
static const struct
@@ -1853,10 +1867,6 @@ static void test_WriteCharEntity(void)
static void test_WriteString(void)
{
- static const WCHAR markupW[] = {'<','&','"','>','=',0};
- static const WCHAR aW[] = {'a',0};
- static const WCHAR bW[] = {'b',0};
- static const WCHAR emptyW[] = {0};
IXmlWriter *writer;
IStream *stream;
HRESULT hr;
@@ -1866,31 +1876,31 @@ static void test_WriteString(void)
writer_set_property(writer, XmlWriterProperty_OmitXmlDeclaration);
- hr = IXmlWriter_WriteString(writer, aW);
+ hr = write_string(writer, "a");
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL);
+ hr = write_string(writer, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, emptyW);
+ hr = write_string(writer, "");
ok(hr == E_UNEXPECTED, "got 0x%08x\n", hr);
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
+ hr = write_start_element(writer, NULL, "b", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL);
+ hr = write_string(writer, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, emptyW);
+ hr = write_string(writer, "");
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, aW);
+ hr = write_string(writer, "a");
ok(hr == S_OK, "got 0x%08x\n", hr);
/* WriteString automatically escapes markup characters */
- hr = IXmlWriter_WriteString(writer, markupW);
+ hr = write_string(writer, "<&\">=");
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer);
@@ -1902,10 +1912,10 @@ static void test_WriteString(void)
stream = writer_set_output(writer);
- hr = IXmlWriter_WriteStartElement(writer, NULL, bW, NULL);
+ hr = write_start_element(writer, NULL, "b", NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
- hr = IXmlWriter_WriteString(writer, NULL);
+ hr = write_string(writer, NULL);
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer);
@@ -1914,7 +1924,7 @@ static void test_WriteString(void)
CHECK_OUTPUT(stream,
"<b");
- hr = IXmlWriter_WriteString(writer, emptyW);
+ hr = write_string(writer, "");
ok(hr == S_OK, "got 0x%08x\n", hr);
hr = IXmlWriter_Flush(writer);
@@ -1923,6 +1933,54 @@ static void test_WriteString(void)
CHECK_OUTPUT(stream,
"<b>");
+ IStream_Release(stream);
+ IXmlWriter_Release(writer);
+
+ /* With indentation */
+ hr = CreateXmlWriter(&IID_IXmlWriter, (void **)&writer, NULL);
+ ok(hr == S_OK, "Failed to create a writer, hr %#x.\n", hr);
+
+ stream = writer_set_output(writer);
+
+ writer_set_property(writer, XmlWriterProperty_Indent);
+
+ hr = write_start_element(writer, NULL, "a", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_start_element(writer, NULL, "b", NULL);
+ ok(hr == S_OK, "Failed to start element, hr %#x.\n", hr);
+
+ hr = write_string(writer, "text");
+ ok(hr == S_OK, "Failed to write a string, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b>text");
+
+ hr = IXmlWriter_WriteFullEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b>text</b>");
+
+ hr = IXmlWriter_WriteFullEndElement(writer);
+ ok(hr == S_OK, "Failed to end element, hr %#x.\n", hr);
+
+ hr = IXmlWriter_Flush(writer);
+ ok(hr == S_OK, "Failed to flush, hr %#x.\n", hr);
+
+ CHECK_OUTPUT(stream,
+ "<a>\r\n"
+ " <b>text</b>\r\n"
+ "</a>");
+
IXmlWriter_Release(writer);
IStream_Release(stream);
}
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c
index 92217b8a4d..94e1f2f8a8 100644
--- a/dlls/xmllite/writer.c
+++ b/dlls/xmllite/writer.c
@@ -80,6 +80,7 @@ typedef struct
xml_encoding encoding;
WCHAR *encoding_name; /* exactly as specified on output creation */
struct output_buffer buffer;
+ DWORD written : 1;
} xmlwriteroutput;
static const struct IUnknownVtbl xmlwriteroutputvtbl;
@@ -114,9 +115,9 @@ typedef struct _xmlwriter
BOOL omitxmldecl;
XmlConformanceLevel conformance;
XmlWriterState state;
- BOOL bomwritten;
- BOOL starttagopen;
struct list elements;
+ DWORD bomwritten : 1;
+ DWORD starttagopen : 1;
} xmlwriter;
static inline xmlwriter *impl_from_IXmlWriter(IXmlWriter *iface)
@@ -438,6 +439,7 @@ static HRESULT write_output_buffer(xmlwriteroutput *output, const WCHAR *data, i
length = WideCharToMultiByte(buffer->codepage, 0, data, len, ptr, length, NULL, NULL);
buffer->written += len == -1 ? length-1 : length;
}
+ output->written = length != 0;
return S_OK;
}
@@ -603,7 +605,7 @@ static HRESULT writer_close_starttag(xmlwriter *writer)
writer_output_ns(writer, LIST_ENTRY(list_head(&writer->elements), struct element, entry));
hr = write_output_buffer(writer->output, gtW, ARRAY_SIZE(gtW));
- writer->starttagopen = FALSE;
+ writer->starttagopen = 0;
return hr;
}
@@ -629,7 +631,7 @@ static void write_node_indent(xmlwriter *writer)
/* Do state check to prevent newline inserted after BOM. It is assumed that
state does not change between writing BOM and inserting indentation. */
- if (writer->output->buffer.written && writer->state != XmlWriterState_Ready)
+ if (writer->output->written && writer->state != XmlWriterState_Ready)
write_output_buffer(writer->output, crlfW, ARRAY_SIZE(crlfW));
while (indent_level--)
write_output_buffer(writer->output, dblspaceW, ARRAY_SIZE(dblspaceW));
@@ -701,7 +703,7 @@ static HRESULT WINAPI xmlwriter_SetOutput(IXmlWriter *iface, IUnknown *output)
writeroutput_release_stream(This->output);
IUnknown_Release(&This->output->IXmlWriterOutput_iface);
This->output = NULL;
- This->bomwritten = FALSE;
+ This->bomwritten = 0;
This->indent_level = 0;
writer_free_element_stack(This);
}
@@ -1211,7 +1213,7 @@ static HRESULT WINAPI xmlwriter_WriteEndElement(IXmlWriter *iface)
{
writer_output_ns(This, element);
write_output_buffer(This->output, closetagW, ARRAY_SIZE(closetagW));
- This->starttagopen = FALSE;
+ This->starttagopen = 0;
}
else
{
@@ -1551,7 +1553,7 @@ static HRESULT WINAPI xmlwriter_WriteStartElement(IXmlWriter *iface, LPCWSTR pre
write_node_indent(This);
This->state = XmlWriterState_ElemStarted;
- This->starttagopen = TRUE;
+ This->starttagopen = 1;
writer_push_element(This, element);
@@ -1772,8 +1774,8 @@ HRESULT WINAPI CreateXmlWriter(REFIID riid, void **obj, IMalloc *imalloc)
writer->omitxmldecl = FALSE;
writer->conformance = XmlConformanceLevel_Document;
writer->state = XmlWriterState_Initial;
- writer->bomwritten = FALSE;
- writer->starttagopen = FALSE;
+ writer->bomwritten = 0;
+ writer->starttagopen = 0;
list_init(&writer->elements);
hr = IXmlWriter_QueryInterface(&writer->IXmlWriter_iface, riid, obj);
@@ -1819,6 +1821,7 @@ static HRESULT create_writer_output(IUnknown *stream, IMalloc *imalloc, xml_enco
}
else
writeroutput->encoding_name = NULL;
+ writeroutput->written = 0;
IUnknown_QueryInterface(stream, &IID_IUnknown, (void**)&writeroutput->output);
--
2.18.0
Sept. 14, 2018
[PATCH 1/5] xmllite/writer: Free finished element data (Valgrind).
by Nikolay Sivov
Signed-off-by: Nikolay Sivov <nsivov(a)codeweavers.com>
---
dlls/xmllite/writer.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/dlls/xmllite/writer.c b/dlls/xmllite/writer.c
index aa6ff7f92a..92217b8a4d 100644
--- a/dlls/xmllite/writer.c
+++ b/dlls/xmllite/writer.c
@@ -1221,6 +1221,7 @@ static HRESULT WINAPI xmlwriter_WriteEndElement(IXmlWriter *iface)
write_output_buffer(This->output, element->qname, element->len);
write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW));
}
+ writer_free_element(This, element);
return S_OK;
}
@@ -1287,6 +1288,8 @@ static HRESULT WINAPI xmlwriter_WriteFullEndElement(IXmlWriter *iface)
write_output_buffer(This->output, element->qname, element->len);
write_output_buffer(This->output, gtW, ARRAY_SIZE(gtW));
+ writer_free_element(This, element);
+
return S_OK;
}
--
2.18.0
Sept. 14, 2018
Re: [PATCH] ntoskrnl: Add FsRtlIsNameInExpression stub.
by Jactry Zeng
Thanks Alistair! An improved version was sent.
Alistair Leslie-Hughes <leslie_alistair(a)hotmail.com> 于2018年9月14日周五 下午4:33写道:
>
>
> On 14/09/18 16:10, Jactry Zeng wrote:
> > dlls/ntoskrnl.exe/ntoskrnl.exe.spec | 2 +-
> > 2 files changed, 11 insertions(+), 1 deletion(-)
> >
> > diff --git a/dlls/ntoskrnl.exe/ntoskrnl.c b/dlls/ntoskrnl.exe/ntoskrnl.c
> > index 18524afb07..9fbf22d71f 100644
> > --- a/dlls/ntoskrnl.exe/ntoskrnl.c
> > +++ b/dlls/ntoskrnl.exe/ntoskrnl.c
> > @@ -2047,6 +2047,16 @@ NTSTATUS WINAPI ExInitializeZone(PZONE_HEADER Zone,
> > return STATUS_NOT_IMPLEMENTED;
> > }
> >
> > +/***********************************************************************
> > +* FsRtlIsNameInExpression (NTOSKRNL.EXE.@)
> > +*/
> > +BOOLEAN WINAPI FsRtlIsNameInExpression(PUNICODE_STRING expression, PUNICODE_STRING name,
> >
> Can you please add it into ntifs.h as well?
>
>
> Thanks
>
> Alistair.
>
>
--
Regards,
Jactry Zeng
Sept. 14, 2018