From: Alanas Tebuev alanas.00@mail.ru
• Multiplication by 2 (also known as sizeof(WCHAR)) happens inside COMCTL32_AdjustUnicodeBuffer. • Use DWORD instead of INT for COMCTL32_UnicodeBuffer.sizeInBytes for consistency with Alloc and negative buffer size doesn't make sense. • Don't forget old COMCTL32_UnicodeBuffer.address when ReAlloc returns NULL. --- dlls/comctl32/comctl32.h | 12 ++++++++++++ dlls/comctl32/commctrl.c | 24 ++++++++++++++++++++++++ dlls/comctl32/pager.c | 36 +++++++++++------------------------- 3 files changed, 47 insertions(+), 25 deletions(-)
diff --git a/dlls/comctl32/comctl32.h b/dlls/comctl32/comctl32.h index f44b4ae132f..283c809e429 100644 --- a/dlls/comctl32/comctl32.h +++ b/dlls/comctl32/comctl32.h @@ -216,6 +216,18 @@ typedef struct int running; } SUBCLASS_INFO, *LPSUBCLASS_INFO;
+/* WM_NOTIFY unicode to ansi conversion and forwarding stuff */ + +/* COMCTL32_UnicodeBuffer is for storing result of ansi to unicode conversion that happens after SendMessageW */ +/* (b.address==NULL)==(b.sizeInBytes==0) && (b.sizeInBytes&1)==0 should always be true (b is COMCTL32_UnicodeBuffer) */ +typedef struct +{ + WCHAR *address; + DWORD sizeInBytes; +} COMCTL32_UnicodeBuffer; + +BOOL COMCTL32_AdjustUnicodeBuffer(COMCTL32_UnicodeBuffer *unicodeBuffer, DWORD minWChars); + /* undocumented functions */
BOOL WINAPI Free (LPVOID); diff --git a/dlls/comctl32/commctrl.c b/dlls/comctl32/commctrl.c index d87e63e813e..a26607f20dd 100644 --- a/dlls/comctl32/commctrl.c +++ b/dlls/comctl32/commctrl.c @@ -2691,3 +2691,27 @@ LRESULT WINAPI SendNotifyEx(HWND hwndTo, HWND hwndFrom, UINT code, NMHDR *hdr, D
return DoNotify(¬ify, code, hdr); } + +/* grow a COMCTL32_UnicodeBuffer if needed so it can hold at least minWChars WCHARs */ +/* return FALSE means failed (unicodeBuffer still valid but too small) */ +/* return TRUE means successful */ +BOOL COMCTL32_AdjustUnicodeBuffer(COMCTL32_UnicodeBuffer *unicodeBuffer, DWORD minWChars) +{ + WCHAR *address; + DWORD minSizeInBytes; + + if (minWChars > (DWORD)-1 / sizeof(WCHAR)) + return FALSE; + minSizeInBytes = minWChars * sizeof(WCHAR); + if (unicodeBuffer->sizeInBytes >= minSizeInBytes) + return TRUE; + address = unicodeBuffer->address; + address = address ? ReAlloc(address, minSizeInBytes) : Alloc(minSizeInBytes); + if (!address) + return FALSE; + *unicodeBuffer = (COMCTL32_UnicodeBuffer) { + .address = address, + .sizeInBytes = minSizeInBytes + }; + return TRUE; +} diff --git a/dlls/comctl32/pager.c b/dlls/comctl32/pager.c index 07484c6ebf5..4e534f13fb9 100644 --- a/dlls/comctl32/pager.c +++ b/dlls/comctl32/pager.c @@ -84,8 +84,7 @@ typedef struct INT TLbtnState; /* state of top or left btn */ INT BRbtnState; /* state of bottom or right btn */ INT direction; /* direction of the scroll, (e.g. PGF_SCROLLUP) */ - WCHAR *pwszBuffer;/* text buffer for converted notifications */ - INT nBufferSize;/* size of the above buffer */ + COMCTL32_UnicodeBuffer unicodeBuffer;/* used in WN_NOTIFY forwarding if bUnicode */ } PAGER_INFO;
#define TIMERID1 1 @@ -611,7 +610,7 @@ static LRESULT PAGER_Destroy (PAGER_INFO *infoPtr) { SetWindowLongPtrW (infoPtr->hwndSelf, 0, 0); - Free (infoPtr->pwszBuffer); + Free (infoPtr->unicodeBuffer.address); Free (infoPtr); return 0; } @@ -1096,19 +1095,6 @@ static UINT PAGER_GetAnsiNtfCode(UINT code) return code; }
-static BOOL PAGER_AdjustBuffer(PAGER_INFO *infoPtr, INT size) -{ - if (!infoPtr->pwszBuffer) - infoPtr->pwszBuffer = Alloc(size); - else if (infoPtr->nBufferSize < size) - infoPtr->pwszBuffer = ReAlloc(infoPtr->pwszBuffer, size); - - if (!infoPtr->pwszBuffer) return FALSE; - if (infoPtr->nBufferSize < size) infoPtr->nBufferSize = size; - - return TRUE; -} - /* Convert text to Unicode and return the original text address */ static WCHAR *PAGER_ConvertText(WCHAR **text) { @@ -1229,7 +1215,7 @@ static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr) { NMDATETIMEFORMATW *nmdtf = (NMDATETIMEFORMATW *)hdr; WCHAR *oldFormat; - INT textLength; + DWORD textLength;
hdr->code = PAGER_GetAnsiNtfCode(hdr->code); oldFormat = PAGER_ConvertText((WCHAR **)&nmdtf->pszFormat); @@ -1239,14 +1225,14 @@ static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr) if (nmdtf->pszDisplay) { textLength = MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmdtf->pszDisplay, -1, 0, 0); - if (!PAGER_AdjustBuffer(infoPtr, textLength * sizeof(WCHAR))) return ret; - MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmdtf->pszDisplay, -1, infoPtr->pwszBuffer, textLength); + if (!COMCTL32_AdjustUnicodeBuffer(&infoPtr->unicodeBuffer, textLength)) return ret; + MultiByteToWideChar(CP_ACP, 0, (LPCSTR)nmdtf->pszDisplay, -1, infoPtr->unicodeBuffer.address, textLength); if (nmdtf->pszDisplay != nmdtf->szDisplay) - nmdtf->pszDisplay = infoPtr->pwszBuffer; + nmdtf->pszDisplay = infoPtr->unicodeBuffer.address; else { textLength = min(textLength, ARRAY_SIZE(nmdtf->szDisplay)); - memcpy(nmdtf->szDisplay, infoPtr->pwszBuffer, textLength * sizeof(WCHAR)); + memcpy(nmdtf->szDisplay, infoPtr->unicodeBuffer.address, textLength * sizeof(WCHAR)); } }
@@ -1346,7 +1332,7 @@ static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr) { NMTTDISPINFOW *nmttdiW = (NMTTDISPINFOW *)hdr; NMTTDISPINFOA nmttdiA = {{0}}; - INT size; + DWORD size;
nmttdiA.hdr.code = PAGER_GetAnsiNtfCode(nmttdiW->hdr.code); nmttdiA.hdr.hwndFrom = nmttdiW->hdr.hwndFrom; @@ -1373,9 +1359,9 @@ static LRESULT PAGER_Notify(PAGER_INFO *infoPtr, NMHDR *hdr) size = MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, 0, 0); if (size > ARRAY_SIZE(nmttdiW->szText)) { - if (!PAGER_AdjustBuffer(infoPtr, size * sizeof(WCHAR))) return ret; - MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, infoPtr->pwszBuffer, size); - nmttdiW->lpszText = infoPtr->pwszBuffer; + if (!COMCTL32_AdjustUnicodeBuffer(&infoPtr->unicodeBuffer, size)) return ret; + MultiByteToWideChar(CP_ACP, 0, nmttdiA.lpszText, -1, infoPtr->unicodeBuffer.address, size); + nmttdiW->lpszText = infoPtr->unicodeBuffer.address; /* Override content in szText */ memcpy(nmttdiW->szText, nmttdiW->lpszText, min(sizeof(nmttdiW->szText), size * sizeof(WCHAR))); }