This MR separates comctl32 into v5 and v6. A full branch is at https://gitlab.winehq.org/zhiyi/wine/-/commits/comctl32-separation. The remaining commits are to remove items that shouldn't be in v5. comctl32-version_6 in wine-staging can be dropped after this MR.
-- v5: comctl32: Separate v5 and v6.
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/comctl32/tests/datetime.c | 2 ++ 1 file changed, 2 insertions(+)
diff --git a/dlls/comctl32/tests/datetime.c b/dlls/comctl32/tests/datetime.c index e2a2967e831..0f15f88b9b0 100644 --- a/dlls/comctl32/tests/datetime.c +++ b/dlls/comctl32/tests/datetime.c @@ -722,6 +722,8 @@ static void test_dtm_set_and_get_system_time(void) expect(4, (LRESULT)getSt.wDayOfWeek); st.wDayOfWeek = 4; expect_systime(&st, &getSt); + + DestroyWindow(hWnd); }
static void test_dtm_set_and_get_systemtime_with_limits(void)
From: Zhiyi Zhang zzhang@codeweavers.com
So that versioned window classes gets registered as well. Otherwise, comctl32 v6 fails to register its window classes when comctl32 v5 window classes are still being used. This can happen, for example, when creating a window using comctl32 v5, then unload comctl32 v5 and not destroying the window, and then load comctl32 v6. --- dlls/user32/class.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/dlls/user32/class.c b/dlls/user32/class.c index b51783da64e..da15f1ef6f1 100644 --- a/dlls/user32/class.c +++ b/dlls/user32/class.c @@ -225,7 +225,8 @@ void get_class_version( UNICODE_STRING *name, UNICODE_STRING *version, BOOL load { if (load && !(hmod = GetModuleHandleW( L"comctl32" ))) hmod = LoadLibraryW( L"comctl32" ); } - else if (!RtlFindActivationContextSectionString( 0, NULL, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, name, &data )) + + if (!RtlFindActivationContextSectionString( 0, NULL, ACTIVATION_CONTEXT_SECTION_WINDOW_CLASS_REDIRECTION, name, &data )) { struct wndclass_redirect_data {
From: Zhiyi Zhang zzhang@codeweavers.com
--- dlls/comctl32/tests/misc.c | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/dlls/comctl32/tests/misc.c b/dlls/comctl32/tests/misc.c index bb3f1993a83..6da3a4536de 100644 --- a/dlls/comctl32/tests/misc.c +++ b/dlls/comctl32/tests/misc.c @@ -22,6 +22,7 @@ #include <windows.h> #include <commctrl.h> #include <uxtheme.h> +#include <shlwapi.h>
#include "wine/test.h" #include "v6util.h" @@ -37,6 +38,7 @@ static BOOL (WINAPI * pStr_SetPtrA)(LPSTR, LPCSTR); static INT (WINAPI * pStr_GetPtrW)(LPCWSTR, LPWSTR, INT); static BOOL (WINAPI * pStr_SetPtrW)(LPWSTR, LPCWSTR);
+static HRESULT (WINAPI *pDllGetVersion)(DLLVERSIONINFO *); static BOOL (WINAPI *pSetWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR, DWORD_PTR); static BOOL (WINAPI *pRemoveWindowSubclass)(HWND, SUBCLASSPROC, UINT_PTR); static LRESULT (WINAPI *pDefSubclassProc)(HWND, UINT, WPARAM, LPARAM); @@ -92,6 +94,8 @@ static BOOL InitFunctionPtrs(void) COMCTL32_GET_PROC(235, Str_GetPtrW) COMCTL32_GET_PROC(236, Str_SetPtrW)
+ pDllGetVersion = (void *)GetProcAddress(hComctl32, "DllGetVersion"); + return TRUE; }
@@ -108,6 +112,8 @@ static BOOL init_functions_v6(void) COMCTL32_GET_PROC(412, RemoveWindowSubclass) COMCTL32_GET_PROC(413, DefSubclassProc)
+ pDllGetVersion = (void *)GetProcAddress(hComctl32, "DllGetVersion"); + return TRUE; }
@@ -1271,6 +1277,19 @@ static void test_WM_SETFONT(void) DestroyWindow(parent); }
+static void test_version(BOOL v6) +{ + DLLVERSIONINFO info; + HRESULT hr; + + info.cbSize = sizeof(info); + hr = pDllGetVersion(&info); + ok(hr == S_OK, "DllGetVersion failed, hr %#lx.\n", hr); + + todo_wine_if(v6) + ok(info.dwMajorVersion == (v6 ? 6 : 5), "Got unexpected major version %lu.\n", info.dwMajorVersion); +} + START_TEST(misc) { ULONG_PTR ctx_cookie; @@ -1285,6 +1304,7 @@ START_TEST(misc) test_comctl32_classes(FALSE); test_WM_STYLECHANGED(); test_WM_SETFONT(); + test_version(FALSE);
FreeLibrary(hComctl32);
@@ -1301,6 +1321,7 @@ START_TEST(misc) test_WM_SYSCOLORCHANGE(); test_WM_STYLECHANGED(); test_WM_SETFONT(); + test_version(TRUE);
unload_v6_module(ctx_cookie, hCtx); FreeLibrary(hComctl32);
From: Zhiyi Zhang zzhang@codeweavers.com
Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=38987 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=49453 Wine-Bug: https://bugs.winehq.org/show_bug.cgi?id=52633 --- MAINTAINERS | 1 + configure.ac | 1 + dlls/comctl32/comctl32.rc | 12 +- ...comctl32.manifest => comctl32_v6.manifest} | 0 dlls/comctl32/tests/misc.c | 1 - dlls/comctl32_v6/Makefile.in | 53 +++++ dlls/comctl32_v6/comctl32_v6.spec | 200 ++++++++++++++++++ dlls/ntdll/unix/loader.c | 51 ++++- dlls/ntdll/unix/unix_private.h | 13 ++ include/commctrl.h | 2 + loader/wine.inf.in | 6 + 11 files changed, 334 insertions(+), 6 deletions(-) rename dlls/comctl32/{comctl32.manifest => comctl32_v6.manifest} (100%) create mode 100644 dlls/comctl32_v6/Makefile.in create mode 100644 dlls/comctl32_v6/comctl32_v6.spec
diff --git a/MAINTAINERS b/MAINTAINERS index cb9c6ce4554..8828d9ad50a 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -58,6 +58,7 @@ Common Controls Library P: Nikolay Sivov nsivov@codeweavers.com P: Zhiyi Zhang zzhang@codeweavers.com F: dlls/comctl32/ +F: dlls/comctl32_v6/
Common Item Dialog P: Esme Povirk esme@codeweavers.com diff --git a/configure.ac b/configure.ac index c8dadcf9bff..7778c450078 100644 --- a/configure.ac +++ b/configure.ac @@ -2497,6 +2497,7 @@ WINE_CONFIG_MAKEFILE(dlls/comcat) WINE_CONFIG_MAKEFILE(dlls/comcat/tests) WINE_CONFIG_MAKEFILE(dlls/comctl32) WINE_CONFIG_MAKEFILE(dlls/comctl32/tests) +WINE_CONFIG_MAKEFILE(dlls/comctl32_v6) WINE_CONFIG_MAKEFILE(dlls/comdlg32) WINE_CONFIG_MAKEFILE(dlls/comdlg32/tests) WINE_CONFIG_MAKEFILE(dlls/coml2) diff --git a/dlls/comctl32/comctl32.rc b/dlls/comctl32/comctl32.rc index 2c62dbe2720..b7631b6766c 100644 --- a/dlls/comctl32/comctl32.rc +++ b/dlls/comctl32/comctl32.rc @@ -113,12 +113,18 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#define WINE_FILEDESCRIPTION_STR "Wine Common Controls" #define WINE_FILENAME_STR "comctl32.dll" -#define WINE_FILEVERSION COMCTL32_VERSION,81,4704,1100 +#if COMCTL32_VERSION == 6 +#define WINE_FILEVERSION 6,0,2600,2982 +#else +#define WINE_FILEVERSION 5,81,4704,1100 +#endif
#include "wine/wine_common_ver.rc"
-/* @makedep: comctl32.manifest */ -WINE_MANIFEST RT_MANIFEST comctl32.manifest +#if COMCTL32_VERSION == 6 +/* @makedep: comctl32_v6.manifest */ +WINE_MANIFEST RT_MANIFEST comctl32_v6.manifest +#endif
/* @makedep: idt_check.bmp */ IDT_CHECK BITMAP idt_check.bmp diff --git a/dlls/comctl32/comctl32.manifest b/dlls/comctl32/comctl32_v6.manifest similarity index 100% rename from dlls/comctl32/comctl32.manifest rename to dlls/comctl32/comctl32_v6.manifest diff --git a/dlls/comctl32/tests/misc.c b/dlls/comctl32/tests/misc.c index 6da3a4536de..6d249000df9 100644 --- a/dlls/comctl32/tests/misc.c +++ b/dlls/comctl32/tests/misc.c @@ -1286,7 +1286,6 @@ static void test_version(BOOL v6) hr = pDllGetVersion(&info); ok(hr == S_OK, "DllGetVersion failed, hr %#lx.\n", hr);
- todo_wine_if(v6) ok(info.dwMajorVersion == (v6 ? 6 : 5), "Got unexpected major version %lu.\n", info.dwMajorVersion); }
diff --git a/dlls/comctl32_v6/Makefile.in b/dlls/comctl32_v6/Makefile.in new file mode 100644 index 00000000000..e218f0add4d --- /dev/null +++ b/dlls/comctl32_v6/Makefile.in @@ -0,0 +1,53 @@ +MODULE = comctl32_v6.dll +IMPORTS = uuid user32 gdi32 advapi32 imm32 kernelbase oleaut32 +DELAYIMPORTS = oleacc winmm uxtheme +EXTRADEFS = -D_COMCTL32_ -DCOMCTL32_VERSION=6 +PARENTSRC = ../comctl32 + +SOURCES = \ + animate.c \ + button.c \ + combo.c \ + comboex.c \ + comctl32.rc \ + commctrl.c \ + datetime.c \ + dpa.c \ + draglist.c \ + dsa.c \ + edit.c \ + flatsb.c \ + header.c \ + hotkey.c \ + idb_hist_large.svg \ + idb_hist_small.svg \ + idb_std_large.svg \ + idb_std_small.svg \ + idb_view_large.svg \ + idb_view_small.svg \ + idc_copy.svg \ + idc_divider.svg \ + idc_divideropen.svg \ + idc_movebutton.svg \ + imagelist.c \ + ipaddress.c \ + listbox.c \ + listview.c \ + monthcal.c \ + nativefont.c \ + pager.c \ + progress.c \ + propsheet.c \ + rebar.c \ + smoothscroll.c \ + static.c \ + status.c \ + string.c \ + syslink.c \ + tab.c \ + taskdialog.c \ + toolbar.c \ + tooltips.c \ + trackbar.c \ + treeview.c \ + updown.c diff --git a/dlls/comctl32_v6/comctl32_v6.spec b/dlls/comctl32_v6/comctl32_v6.spec new file mode 100644 index 00000000000..73f25906205 --- /dev/null +++ b/dlls/comctl32_v6/comctl32_v6.spec @@ -0,0 +1,200 @@ +# Functions exported by the Win95 comctl32.dll +# (these need to have these exact ordinals, because some win95 dlls +# import comctl32.dll by ordinal) +# This list was created from a comctl32.dll v5.81 (IE5.01). + + 2 stdcall MenuHelp(long long long long long long ptr) + 3 stdcall ShowHideMenuCtl(long long ptr) + 4 stdcall GetEffectiveClientRect(long ptr ptr) + 5 stdcall DrawStatusTextA(long ptr str long) + 6 stdcall CreateStatusWindowA(long str long long) + 7 stdcall CreateToolbar(long long long long long long ptr long) + 8 stdcall CreateMappedBitmap(long long long ptr long) + 9 stdcall -noname DPA_LoadStream(ptr ptr ptr ptr) + 10 stdcall -noname DPA_SaveStream(ptr ptr ptr ptr) + 11 stdcall -noname DPA_Merge(ptr ptr long ptr ptr long) +#12 stub Cctl1632_ThunkData32 + 13 stdcall MakeDragList(long) + 14 stdcall LBItemFromPt(long int64 long) + 15 stdcall DrawInsert(long long long) + 16 stdcall CreateUpDownControl(long long long long long long long long long long long long) + 17 stdcall InitCommonControls() + 71 stdcall -noname Alloc(long) + 72 stdcall -noname ReAlloc(ptr long) + 73 stdcall -noname Free(ptr) + 74 stdcall -noname GetSize(ptr) +151 stdcall -noname CreateMRUListA(ptr) +152 stdcall -noname FreeMRUList(long) +153 stdcall -noname AddMRUStringA(long str) +154 stdcall -noname EnumMRUListA(long long ptr long) +155 stdcall -noname FindMRUStringA(long str ptr) +156 stdcall -noname DelMRUString(long long) +157 stdcall -noname CreateMRUListLazyA(ptr long long long) +163 stub -noname CreatePage +164 stub -noname CreateProxyPage +167 stdcall -noname AddMRUData(long ptr long) +169 stdcall -noname FindMRUData(long ptr long ptr) +233 stdcall -noname Str_GetPtrA(str str long) +234 stdcall -noname Str_SetPtrA(ptr str) +235 stdcall -noname Str_GetPtrW(wstr wstr long) +236 stdcall -noname Str_SetPtrW(ptr wstr) +320 stdcall -ordinal DSA_Create(long long) +321 stdcall -ordinal DSA_Destroy(ptr) +322 stdcall -ordinal DSA_GetItem(ptr long ptr) +323 stdcall -ordinal DSA_GetItemPtr(ptr long) +324 stdcall -ordinal DSA_InsertItem(ptr long ptr) +325 stdcall -ordinal DSA_SetItem (ptr long ptr) +326 stdcall -ordinal DSA_DeleteItem(ptr long) +327 stdcall -ordinal DSA_DeleteAllItems(ptr) +328 stdcall -ordinal DPA_Create(long) +329 stdcall -ordinal DPA_Destroy(ptr) +330 stdcall -ordinal DPA_Grow(ptr long) +331 stdcall -ordinal DPA_Clone(ptr ptr) +332 stdcall -ordinal DPA_GetPtr(ptr long) +333 stdcall -ordinal DPA_GetPtrIndex(ptr ptr) +334 stdcall -ordinal DPA_InsertPtr(ptr long ptr) +335 stdcall -ordinal DPA_SetPtr(ptr long ptr) +336 stdcall -ordinal DPA_DeletePtr(ptr long) +337 stdcall -ordinal DPA_DeleteAllPtrs(ptr) +338 stdcall -ordinal DPA_Sort(ptr ptr long) +339 stdcall -ordinal DPA_Search(ptr ptr long ptr long long) +340 stdcall -ordinal DPA_CreateEx(long long) +341 stdcall -noname SendNotify(long long long ptr) +342 stdcall -noname SendNotifyEx(long long long ptr long) +344 stdcall -ordinal TaskDialog(long long wstr wstr wstr long wstr ptr) +345 stdcall -ordinal TaskDialogIndirect(ptr ptr ptr ptr) +350 stdcall -noname -private StrChrA(str long) kernelbase.StrChrA +351 stdcall -noname -private StrRChrA(str str long) kernelbase.StrRChrA +352 stdcall -noname -private StrCmpNA(str str long) kernelbase.StrCmpNA +353 stdcall -noname -private StrCmpNIA(str str long) kernelbase.StrCmpNIA +354 stdcall -noname -private StrStrA(str str) kernelbase.StrStrA +355 stdcall -noname -private StrStrIA(str str) kernelbase.StrStrIA +356 stdcall -noname -private StrCSpnA(str str) kernelbase.StrCSpnA +357 stdcall -noname -private StrToIntA(str) kernelbase.StrToIntA +358 stdcall -noname -private StrChrW(wstr long) kernelbase.StrChrW +359 stdcall -noname -private StrRChrW(wstr wstr long) kernelbase.StrRChrW +360 stdcall -noname -private StrCmpNW(wstr wstr long) kernelbase.StrCmpNW +361 stdcall -noname -private StrCmpNIW(wstr wstr long) kernelbase.StrCmpNIW +362 stdcall -noname -private StrStrW(wstr wstr) kernelbase.StrStrW +363 stdcall -noname -private StrStrIW(wstr wstr) kernelbase.StrStrIW +364 stdcall -noname -private StrCSpnW(wstr wstr) kernelbase.StrCSpnW +365 stdcall -noname -private StrToIntW(wstr) kernelbase.StrToIntW +366 stdcall -noname -private StrChrIA(str long) kernelbase.StrChrIA +367 stdcall -noname -private StrChrIW(wstr long) kernelbase.StrChrIW +368 stdcall -noname -private StrRChrIA(str str long) kernelbase.StrRChrIA +369 stdcall -noname -private StrRChrIW(wstr wstr long) kernelbase.StrRChrIW +372 stdcall -noname -private StrRStrIA(str str str) kernelbase.StrRStrIA +373 stdcall -noname -private StrRStrIW(wstr wstr wstr) kernelbase.StrRStrIW +374 stdcall -noname -private StrCSpnIA(str str) kernelbase.StrCSpnIA +375 stdcall -noname -private StrCSpnIW(wstr wstr) kernelbase.StrCSpnIW +376 stdcall -noname -private IntlStrEqWorkerA(long str str long) +377 stdcall -noname -private IntlStrEqWorkerW(long wstr wstr long) +380 stdcall -ordinal LoadIconMetric(ptr wstr long ptr) +381 stdcall -ordinal LoadIconWithScaleDown(ptr wstr long long ptr) +382 stdcall -noname SmoothScrollWindow(ptr) +383 stub -noname DoReaderMode +384 stdcall -noname SetPathWordBreakProc(ptr long) +385 stdcall -ordinal DPA_EnumCallback(ptr ptr ptr) +386 stdcall -ordinal DPA_DestroyCallback(ptr ptr ptr) +387 stdcall -ordinal DSA_EnumCallback(ptr ptr ptr) +388 stdcall -ordinal DSA_DestroyCallback(ptr ptr ptr) +389 stub -noname SHGetProcessDword +390 stdcall -noname ImageList_SetColorTable(ptr long long ptr) +400 stdcall -ordinal CreateMRUListW(ptr) +401 stdcall -ordinal AddMRUStringW(long wstr) +402 stdcall -noname FindMRUStringW(long wstr ptr) +403 stdcall -ordinal EnumMRUListW(long long ptr long) +404 stdcall -noname CreateMRUListLazyW(ptr long long long) +410 stdcall -ordinal SetWindowSubclass(long ptr long long) +411 stdcall -ordinal GetWindowSubclass(long ptr long ptr) +412 stdcall -ordinal RemoveWindowSubclass(long ptr long) +413 stdcall -ordinal DefSubclassProc(long long long long) +414 stdcall -noname MirrorIcon(ptr ptr) +415 stdcall -noname DrawTextWrap(long wstr long ptr long) user32.DrawTextW +416 stdcall -noname DrawTextExPrivWrap(long wstr long ptr long ptr) user32.DrawTextExW +417 stdcall -noname ExtTextOutWrap(long long long long ptr wstr long ptr) gdi32.ExtTextOutW +418 stdcall -noname GetCharWidthWrap(long long long long) gdi32.GetCharWidthW +419 stdcall -noname GetTextExtentPointWrap(long wstr long ptr) gdi32.GetTextExtentPointW +420 stdcall -noname GetTextExtentPoint32Wrap(long wstr long ptr) gdi32.GetTextExtentPoint32W +421 stdcall -noname TextOutWrap(long long long wstr long) gdi32.TextOutW + +# Functions imported by name + +@ stdcall CreatePropertySheetPage(ptr) CreatePropertySheetPageA +@ stdcall CreatePropertySheetPageA(ptr) +@ stdcall CreatePropertySheetPageW(ptr) +@ stdcall CreateStatusWindow(long str long long) CreateStatusWindowA +@ stdcall CreateStatusWindowW(long wstr long long) +@ stdcall CreateToolbarEx(long long long long long long ptr long long long long long long) +@ stdcall DestroyPropertySheetPage(long) +@ stdcall -private DllGetVersion(ptr) +@ stdcall -private DllInstall(long wstr) +@ stdcall -ret64 DPA_GetSize(ptr) +@ stdcall DrawShadowText(long wstr long ptr long long long long long) +@ stdcall DrawStatusText(long ptr ptr long) DrawStatusTextA +@ stdcall DrawStatusTextW(long ptr wstr long) +@ stdcall DSA_Clone(ptr) +@ stdcall -ret64 DSA_GetSize(ptr) +@ stdcall FlatSB_EnableScrollBar (long long long) +@ stdcall FlatSB_GetScrollInfo (long long ptr) +@ stdcall FlatSB_GetScrollPos (long long) +@ stdcall FlatSB_GetScrollProp (long long ptr) +@ stdcall FlatSB_GetScrollRange (long long ptr ptr) +@ stdcall FlatSB_SetScrollInfo (long long ptr long) +@ stdcall FlatSB_SetScrollPos (long long long long) +@ stdcall FlatSB_SetScrollProp (long long long long) +@ stdcall FlatSB_SetScrollRange (long long long long long) +@ stdcall FlatSB_ShowScrollBar (long long long) +@ stdcall GetMUILanguage() +@ stdcall HIMAGELIST_QueryInterface(ptr ptr ptr) +@ stdcall ImageList_Add(ptr long long) +@ stdcall ImageList_AddIcon(ptr long) +@ stdcall ImageList_AddMasked(ptr long long) +@ stdcall ImageList_BeginDrag(ptr long long long) +@ stdcall ImageList_CoCreateInstance(ptr ptr ptr ptr) +@ stdcall ImageList_Copy(ptr long ptr long long) +@ stdcall ImageList_Create(long long long long long) +@ stdcall ImageList_Destroy(ptr) +@ stdcall ImageList_DragEnter(long long long) +@ stdcall ImageList_DragLeave(long) +@ stdcall ImageList_DragMove(long long) +@ stdcall ImageList_DragShowNolock(long) +@ stdcall ImageList_Draw(ptr long long long long long) +@ stdcall ImageList_DrawEx(ptr long long long long long long long long long) +@ stdcall ImageList_DrawIndirect(ptr) +@ stdcall ImageList_Duplicate(ptr) +@ stdcall ImageList_EndDrag() +@ stdcall ImageList_GetBkColor(ptr) +@ stdcall ImageList_GetDragImage(ptr ptr) +@ stdcall ImageList_GetFlags(ptr) +@ stdcall ImageList_GetIcon(ptr long long) +@ stdcall ImageList_GetIconSize(ptr ptr ptr) +@ stdcall ImageList_GetImageCount(ptr) +@ stdcall ImageList_GetImageInfo(ptr long ptr) +@ stdcall ImageList_GetImageRect(ptr long ptr) +@ stdcall ImageList_LoadImage(long str long long long long long) ImageList_LoadImageA +@ stdcall ImageList_LoadImageA(long str long long long long long) +@ stdcall ImageList_LoadImageW(long wstr long long long long long) +@ stdcall ImageList_Merge(ptr long ptr long long long) +@ stdcall ImageList_Read(ptr) +@ stdcall ImageList_Remove(ptr long) +@ stdcall ImageList_Replace(ptr long long long) +@ stdcall ImageList_ReplaceIcon(ptr long long) +@ stdcall ImageList_SetBkColor(ptr long) +@ stdcall ImageList_SetDragCursorImage(ptr long long long) +@ stdcall ImageList_SetFilter(ptr long long) +@ stdcall ImageList_SetFlags(ptr long) +@ stdcall ImageList_SetIconSize(ptr long long) +@ stdcall ImageList_SetImageCount(ptr long) +@ stdcall ImageList_SetOverlayImage(ptr long long) +@ stdcall ImageList_Write(ptr ptr) +@ stdcall ImageList_WriteEx(ptr long ptr) +@ stdcall InitCommonControlsEx(ptr) +@ stdcall InitMUILanguage(long) +@ stdcall InitializeFlatSB(long) +@ stdcall PropertySheet(ptr) PropertySheetA +@ stdcall PropertySheetA(ptr) +@ stdcall PropertySheetW(ptr) +@ stdcall RegisterClassNameW(wstr) +@ stdcall UninitializeFlatSB(long) +@ stdcall _TrackMouseEvent(ptr) diff --git a/dlls/ntdll/unix/loader.c b/dlls/ntdll/unix/loader.c index 4e40e09ecf2..6200e1a3b4c 100644 --- a/dlls/ntdll/unix/loader.c +++ b/dlls/ntdll/unix/loader.c @@ -1231,6 +1231,49 @@ static NTSTATUS open_builtin_pe_file( const char *name, OBJECT_ATTRIBUTES *attr, return status; }
+static BOOL is_comctl32_v6( const char *name, UNICODE_STRING *nt_name ) +{ + static const WCHAR prefix[] = {'\','?','?','\'}; + static const WCHAR winsxs_dir[] = {'c',':','\', + 'w','i','n','d','o','w','s','\', + 'w','i','n','s','x','s','\',0}; + static const WCHAR assembly_id[] = {'m','i','c','r','o','s','o','f','t','.', + 'w','i','n','d','o','w','s','.', + 'c','o','m','m','o','n','-', + 'c','o','n','t','r','o','l','s','_', + '6','5','9','5','b','6','4','1','4','4','c','c','f','1','d','f','_', + '6','.','0',0}; + unsigned int i, length; + const WCHAR *path; + BOOL ret = FALSE; + WCHAR *buffer; + + if (strncmp( name, "/comctl32", 9 )) + return FALSE; + + buffer = malloc( nt_name->Length + sizeof(WCHAR) ); + if (!buffer) + return FALSE; + + length = nt_name->Length / sizeof(WCHAR); + for (i = 0; i < length; i++) + { + if (nt_name->Buffer[i] > 127) + goto done; + + buffer[i] = nt_name->Buffer[i]; + if (buffer[i] >= 'A' && buffer[i] <= 'Z') buffer[i] += 'a' - 'A'; + } + buffer[length] = 0; + + path = buffer; + if (!wcsncmp( path, prefix, 4 )) path += 4; + ret = !wcsncmp( winsxs_dir, path, wcslen( winsxs_dir ) ) && wcsstr( path, assembly_id ); + +done: + free( buffer ); + return ret; +}
/*********************************************************************** * find_builtin_dll @@ -1262,11 +1305,11 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T pe_build_dir = alt_build_dir; maxlen = max( strlen(build_dir), strlen(pe_build_dir) ) + sizeof("/programs/") + len; } - maxlen = max( maxlen, dll_path_maxlen + 1 ) + len + sizeof("/aarch64-windows") + sizeof(".so"); + maxlen = max( maxlen, dll_path_maxlen + 1 ) + len + sizeof("/aarch64-windows") + sizeof(".so") + sizeof("_v6.dll");
if (!(file = malloc( maxlen ))) return STATUS_NO_MEMORY;
- pos = maxlen - len - sizeof(".so"); + pos = maxlen - len - sizeof(".so") - sizeof("_v6.dll"); /* we don't want to depend on the current codepage here */ for (i = 0; i < len; i++) { @@ -1278,6 +1321,10 @@ static NTSTATUS find_builtin_dll( UNICODE_STRING *nt_name, void **module, SIZE_T file[pos + len] = 0; file[--pos] = '/';
+ /* find builtin comctl32 v6 */ + if (is_comctl32_v6( file + pos, nt_name )) + strcpy( file + pos, "/comctl32_v6.dll" ); + if (build_dir) { /* try as a dll */ diff --git a/dlls/ntdll/unix/unix_private.h b/dlls/ntdll/unix/unix_private.h index fa38f4b87ca..5b125cf0755 100644 --- a/dlls/ntdll/unix/unix_private.h +++ b/dlls/ntdll/unix/unix_private.h @@ -564,6 +564,18 @@ static inline WCHAR ntdll_towlower( WCHAR ch ) return ch + lctable[lctable[lctable[ch >> 8] + ((ch >> 4) & 0x0f)] + (ch & 0x0f)]; }
+static inline WCHAR *ntdll_wcsstr( const WCHAR *str, const WCHAR *sub ) +{ + while (*str) + { + const WCHAR *p1 = str, *p2 = sub; + while (*p1 && *p2 && *p1 == *p2) { p1++; p2++; } + if (!*p2) return (WCHAR *)str; + str++; + } + return NULL; +} + static inline WCHAR *ntdll_wcsupr( WCHAR *str ) { WCHAR *ret; @@ -571,6 +583,7 @@ static inline WCHAR *ntdll_wcsupr( WCHAR *str ) return ret; }
+#define wcsstr(str, sub) ntdll_wcsstr(str, sub) #define wcsupr(str) ntdll_wcsupr(str) #define towupper(c) ntdll_towupper(c) #define towlower(c) ntdll_towlower(c) diff --git a/include/commctrl.h b/include/commctrl.h index 235704a76dd..b9f8ee8c959 100644 --- a/include/commctrl.h +++ b/include/commctrl.h @@ -59,7 +59,9 @@ enum _LI_METRIC WINCOMMCTRLAPI HRESULT WINAPI LoadIconWithScaleDown(HINSTANCE, const WCHAR *, int, int, HICON *); WINCOMMCTRLAPI HRESULT WINAPI LoadIconMetric(HINSTANCE, const WCHAR *, int, HICON *);
+#ifndef COMCTL32_VERSION #define COMCTL32_VERSION 5 /* dll version */ +#endif
#define ICC_LISTVIEW_CLASSES 0x00000001 /* listview, header */ #define ICC_TREEVIEW_CLASSES 0x00000002 /* treeview, tooltips */ diff --git a/loader/wine.inf.in b/loader/wine.inf.in index 8e6956b3e9f..d374b6f53f2 100644 --- a/loader/wine.inf.in +++ b/loader/wine.inf.in @@ -2265,6 +2265,9 @@ HKLM,SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86,"Version",2,"14.42.344 11,,winemenubuilder.exe,- 11,,wuauserv.exe,- ; registration order matters for these +11,,comctl32.dll,comctl32_v6.dll +11,,comctl32_v6.dll,- +11,,comctl32.dll 11,,msxml.dll 11,,msxml2.dll 11,,msxml3.dll @@ -2318,6 +2321,9 @@ HKLM,SOFTWARE\Microsoft\VisualStudio\14.0\VC\Runtimes\x86,"Version",2,"14.42.344 11,,servicemodelreg.exe,- 11,,presentationfontcache.exe,- ; registration order matters for these +11,,comctl32.dll,comctl32_v6.dll +11,,comctl32_v6.dll,- +11,,comctl32.dll 11,,msxml.dll 11,,msxml2.dll 11,,msxml3.dll
On Sat Jul 19 02:45:01 2025 +0000, Zhiyi Zhang wrote:
The datetime test failures are caused by a datetime window that is still alive after unloading comctl32 v5. Thus, the comctl32 v5 window classes fail to unregister, and then the comctl32 v6 datetime window class fails to register because they use the same name. So the comctl32 v6 datetime window creation failed. The first problem is obviously to destroy the datetime window after it's done. The second problem is that such a failure doesn't happen on Windows. After looking further, comctl32 v6 should get its versioned window classes registered even when comctl32 v5 window classes are kept alive. This is addressed by "user32: Load version for comctl32 v6 window classes.". I'm not sure how to test the patch. It seems that there isn't an API to get the real versioned window class.
FWIW on Windows you can have v5 control next to v6 control, just use ActivateActCtx() and DeactivateActCtx() appropriately when creating such controls, since they share the same *un*versioned name.