Index: dll/win32/comctl32/comctl32.h =================================================================== --- dll/win32/comctl32/comctl32.h (revision 73783) +++ dll/win32/comctl32/comctl32.h (working copy) @@ -165,7 +165,7 @@ int MONTHCAL_CalculateDayOfWeek(SYSTEMTIME *date, BOOL inplace) DECLSPEC_HIDDEN; LONG MONTHCAL_CompareSystemTime(const SYSTEMTIME *first, const SYSTEMTIME *second) DECLSPEC_HIDDEN; -extern void THEMING_Initialize(void) DECLSPEC_HIDDEN; +extern void THEMING_Initialize(HANDLE hActCtx5, HANDLE hActCtx6) DECLSPEC_HIDDEN; extern void THEMING_Uninitialize(void) DECLSPEC_HIDDEN; extern LRESULT THEMING_CallOriginalClass(HWND, UINT, WPARAM, LPARAM) DECLSPEC_HIDDEN; extern void THEMING_SetSubclassData(HWND, ULONG_PTR) DECLSPEC_HIDDEN; Index: dll/win32/comctl32/comctl32.manifest =================================================================== --- dll/win32/comctl32/comctl32.manifest (revision 73783) +++ dll/win32/comctl32/comctl32.manifest (working copy) @@ -1,6 +1,6 @@ - + Button ButtonListBox @@ -12,7 +12,6 @@ NativeFontCtl ReBarWindow32 ScrollBar - Static SysAnimate32 SysDateTimePick32 SysHeader32 Index: dll/win32/comctl32/comctl32v5.manifest =================================================================== --- dll/win32/comctl32/comctl32v5.manifest (nonexistent) +++ dll/win32/comctl32/comctl32v5.manifest (working copy) @@ -0,0 +1,33 @@ + + + + + Button + ButtonListBox + ComboBoxEx32 + ComboLBox + Combobox + Edit + Listbox + NativeFontCtl + ReBarWindow32 + ScrollBar + SysAnimate32 + SysDateTimePick32 + SysHeader32 + SysIPAddress32 + SysLink + SysListView32 + SysMonthCal32 + SysPager + SysTabControl32 + SysTreeView32 + ToolbarWindow32 + msctls_hotkey32 + msctls_progress32 + msctls_statusbar32 + msctls_trackbar32 + msctls_updown32 + tooltips_class32 + + Index: dll/win32/comctl32/commctrl.c =================================================================== --- dll/win32/comctl32/commctrl.c (revision 73783) +++ dll/win32/comctl32/commctrl.c (working copy) @@ -61,6 +61,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(commctrl); #define NAME L"microsoft.windows.common-controls" +#define VERSION_V5 L"5.82.2600.2982" #define VERSION L"6.0.2600.2982" #define PUBLIC_KEY L"6595b64144ccf1df" @@ -73,6 +74,7 @@ #endif static const WCHAR manifest_filename[] = ARCH L"_" NAME L"_" PUBLIC_KEY L"_" VERSION L"_none_deadbeef.manifest"; +static const WCHAR manifest_filename_v5[] = ARCH L"_" NAME L"_" PUBLIC_KEY L"_" VERSION_V5 L"_none_deadbeef.manifest"; static LRESULT WINAPI COMCTL32_SubclassProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); @@ -94,17 +96,51 @@ 'C','C','3','2','S','u','b','c','l','a','s','s','I','n','f','o',0 }; -static BOOL create_manifest(BOOL install) +static WCHAR* GetManifestPath(BOOL create, BOOL bV6) { WCHAR *pwszBuf; + DWORD cchBuf; + + if (bV6) + cchBuf = GetWindowsDirectoryW(NULL, 0) * sizeof(WCHAR) + sizeof(L"\\winsxs\\manifests\\") + sizeof(manifest_filename); + else + cchBuf = GetWindowsDirectoryW(NULL, 0) * sizeof(WCHAR) + sizeof(L"\\winsxs\\manifests\\") + sizeof(manifest_filename_v5); + + pwszBuf = (WCHAR*)HeapAlloc(GetProcessHeap(), 0, cchBuf * sizeof(WCHAR)); + if (!pwszBuf) + return NULL; + + GetWindowsDirectoryW(pwszBuf, cchBuf); + lstrcatW(pwszBuf, L"\\winsxs"); + if (create) + CreateDirectoryW(pwszBuf, NULL); + lstrcatW(pwszBuf, L"\\manifests\\"); + if (create) + CreateDirectoryW(pwszBuf, NULL); + + if (bV6) + lstrcatW(pwszBuf, manifest_filename); + else + lstrcatW(pwszBuf, manifest_filename_v5); + + return pwszBuf; +} + +static BOOL create_manifest(BOOL install, BOOL bV6) +{ + WCHAR *pwszBuf; HRSRC hResInfo; HGLOBAL hResData; PVOID pManifest; - DWORD cchBuf, cbManifest, cbWritten; + DWORD cbManifest, cbWritten; HANDLE hFile; BOOL bRet = FALSE; - hResInfo = FindResourceW(COMCTL32_hModule, L"WINE_MANIFEST", (LPWSTR)RT_MANIFEST); + if (bV6) + hResInfo = FindResourceW(COMCTL32_hModule, L"WINE_MANIFEST", (LPWSTR)RT_MANIFEST); + else + hResInfo = FindResourceW(COMCTL32_hModule, L"WINE_MANIFESTV5", (LPWSTR)RT_MANIFEST); + if (!hResInfo) return FALSE; @@ -120,17 +156,10 @@ if (!pManifest) return FALSE; - cchBuf = GetWindowsDirectoryW(NULL, 0) * sizeof(WCHAR) + sizeof(L"\\winsxs\\manifests\\") + sizeof(manifest_filename); - pwszBuf = (WCHAR*)HeapAlloc(GetProcessHeap(), 0, cchBuf * sizeof(WCHAR)); + pwszBuf = GetManifestPath(TRUE, bV6); if (!pwszBuf) return FALSE; - GetWindowsDirectoryW(pwszBuf, cchBuf); - lstrcatW(pwszBuf, L"\\winsxs"); - CreateDirectoryW(pwszBuf, NULL); - lstrcatW(pwszBuf, L"\\manifests\\"); - CreateDirectoryW(pwszBuf, NULL); - lstrcatW(pwszBuf, manifest_filename); if (install) { hFile = CreateFileW(pwszBuf, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, NULL); @@ -155,7 +184,42 @@ return bRet; } +static HANDLE CreateComctl32ActCtx(BOOL bV6) +{ + HANDLE ret; + ACTCTXW ActCtx = {sizeof(ACTCTX)}; + WCHAR* pwstrSource = GetManifestPath(FALSE, bV6); + ActCtx.lpSource = pwstrSource; + ret = CreateActCtxW(&ActCtx); + HeapFree(GetProcessHeap(), 0, pwstrSource); + return ret; +} +static void RegisterComctl32Classes() +{ + ANIMATE_Register (); + COMBOEX_Register (); + DATETIME_Register (); + FLATSB_Register (); + HEADER_Register (); + HOTKEY_Register (); + IPADDRESS_Register (); + LISTVIEW_Register (); + MONTHCAL_Register (); + NATIVEFONT_Register (); + PAGER_Register (); + PROGRESS_Register (); + REBAR_Register (); + STATUS_Register (); + SYSLINK_Register (); + TAB_Register (); + TOOLBAR_Register (); + TOOLTIPS_Register (); + TRACKBAR_Register (); + TREEVIEW_Register (); + UPDOWN_Register (); +} + /*********************************************************************** * DllMain [Internal] * @@ -173,6 +237,9 @@ BOOL WINAPI DllMain(HINSTANCE hinstDLL, DWORD fdwReason, LPVOID lpvReserved) { + HANDLE hActCtx5, hActCtx6; + BOOL activated; + ULONG_PTR ulCookie; TRACE("%p,%x,%p\n", hinstDLL, fdwReason, lpvReserved); switch (fdwReason) { @@ -189,34 +256,38 @@ COMCTL32_hPattern55AABitmap = CreateBitmap (8, 8, 1, 1, wPattern55AA); COMCTL32_hPattern55AABrush = CreatePatternBrush (COMCTL32_hPattern55AABitmap); - /* Get all the colors at DLL load */ - COMCTL32_RefreshSysColors(); + /* Get all the colors at DLL load */ + COMCTL32_RefreshSysColors(); /* like comctl32 5.82+ register all the common control classes */ - ANIMATE_Register (); - COMBOEX_Register (); - DATETIME_Register (); - FLATSB_Register (); - HEADER_Register (); - HOTKEY_Register (); - IPADDRESS_Register (); - LISTVIEW_Register (); - MONTHCAL_Register (); - NATIVEFONT_Register (); - PAGER_Register (); - PROGRESS_Register (); - REBAR_Register (); - STATUS_Register (); - SYSLINK_Register (); - TAB_Register (); - TOOLBAR_Register (); - TOOLTIPS_Register (); - TRACKBAR_Register (); - TREEVIEW_Register (); - UPDOWN_Register (); + hActCtx5 = CreateComctl32ActCtx(FALSE); + if (hActCtx5 == INVALID_HANDLE_VALUE || !hActCtx5) + ERR("CreateComctl32ActCtx failed\n"); - /* subclass user32 controls */ - THEMING_Initialize (); + hActCtx6 = CreateComctl32ActCtx(TRUE); + if (hActCtx6 == INVALID_HANDLE_VALUE || !hActCtx6) + ERR("CreateComctl32ActCtx failed\n"); + + if (hActCtx5 == INVALID_HANDLE_VALUE || !hActCtx5 || + hActCtx6 == INVALID_HANDLE_VALUE || !hActCtx6) + { + RegisterComctl32Classes(); + THEMING_Initialize (0, 0); + } + else + { + activated = ActivateActCtx(hActCtx5, &ulCookie); + RegisterComctl32Classes(); /* Register the classes pretending to be v5 */ + if (activated) + DeactivateActCtx(0, ulCookie); + + activated = ActivateActCtx(hActCtx6, &ulCookie); + RegisterComctl32Classes(); /* Register the classes pretending to be v6 */ + if (activated) + DeactivateActCtx(0, ulCookie); + + THEMING_Initialize (hActCtx5, hActCtx6); + } break; case DLL_PROCESS_DETACH: @@ -991,12 +1062,18 @@ HRESULT WINAPI DllInstall(BOOL bInstall, LPCWSTR cmdline) { TRACE("(%u, %s): stub\n", bInstall, debugstr_w(cmdline)); - if (!create_manifest(bInstall)) + if (!create_manifest(bInstall, TRUE)) { ERR("create_manifest failed!\n"); return HRESULT_FROM_WIN32(GetLastError()); } + if (!create_manifest(bInstall, FALSE)) + { + ERR("create_manifest failed!\n"); + return HRESULT_FROM_WIN32(GetLastError()); + } + return S_OK; } Index: dll/win32/comctl32/rsrc.rc =================================================================== --- dll/win32/comctl32/rsrc.rc (revision 73783) +++ dll/win32/comctl32/rsrc.rc (working copy) @@ -38,6 +38,7 @@ /* @makedep: comctl32.manifest */ WINE_MANIFEST RT_MANIFEST comctl32.manifest +WINE_MANIFESTV5 RT_MANIFEST comctl32v5.manifest /* @makedep: idt_check.bmp */ IDT_CHECK BITMAP idt_check.bmp Index: dll/win32/comctl32/theming.c =================================================================== --- dll/win32/comctl32/theming.c (revision 73783) +++ dll/win32/comctl32/theming.c (working copy) @@ -48,7 +48,7 @@ THEMING_SUBCLASSPROC subclassProc; } subclasses[] = { /* Note: list must be sorted by class name */ - {dialogClass, THEMING_DialogSubclassProc}, +// {dialogClass, THEMING_DialogSubclassProc}, {WC_BUTTONW, THEMING_ButtonSubclassProc}, {WC_COMBOBOXW, THEMING_ComboSubclassProc}, {comboLboxClass, THEMING_ListBoxSubclassProc}, @@ -90,7 +90,7 @@ MAKE_SUBCLASS_PROC(3) MAKE_SUBCLASS_PROC(4) MAKE_SUBCLASS_PROC(5) -MAKE_SUBCLASS_PROC(6) +//MAKE_SUBCLASS_PROC(6) static const WNDPROC subclassProcs[NUM_SUBCLASSES] = { subclass_proc0, @@ -98,8 +98,8 @@ subclass_proc2, subclass_proc3, subclass_proc4, - subclass_proc5, - subclass_proc6 + subclass_proc5/*, + subclass_proc6*/ }; /*********************************************************************** @@ -108,7 +108,7 @@ * Register classes for standard controls that will shadow the system * classes. */ -void THEMING_Initialize (void) +void THEMING_Initialize (HANDLE hActCtx5, HANDLE hActCtx6) { unsigned int i; static const WCHAR subclassPropName[] = @@ -115,9 +115,10 @@ { 'C','C','3','2','T','h','e','m','i','n','g','S','u','b','C','l',0 }; static const WCHAR refDataPropName[] = { 'C','C','3','2','T','h','e','m','i','n','g','D','a','t','a',0 }; + ULONG_PTR ulCookie; + BOOL ret; + //if (!IsThemeActive()) return; - if (!IsThemeActive()) return; - atSubclassProp = GlobalAddAtomW (subclassPropName); atRefDataProp = GlobalAddAtomW (refDataPropName); @@ -126,7 +127,15 @@ WNDCLASSEXW class; class.cbSize = sizeof(class); - if (!GetClassInfoExW (NULL, subclasses[i].className, &class)) + + if (!ActivateActCtx(hActCtx5, &ulCookie)) + ERR("ActivateActCtx failed\n"); + + ret = GetClassInfoExW (NULL, subclasses[i].className, &class); + + if (!DeactivateActCtx(0, ulCookie)) + ERR("DeactivateActCtx failed\n"); + if (!ret) { ERR("Could not retrieve information for class %s\n", debugstr_w (subclasses[i].className)); @@ -134,6 +143,8 @@ } originalProcs[i] = class.lpfnWndProc; class.lpfnWndProc = subclassProcs[i]; + class.style |= CS_GLOBALCLASS; + class.hInstance = COMCTL32_hModule; if (!class.lpfnWndProc) { @@ -142,6 +153,9 @@ continue; } + if (!ActivateActCtx(hActCtx6, &ulCookie)) + ERR("ActivateActCtx failed\n"); + if (!RegisterClassExW (&class)) { ERR("Could not re-register class %s: %x\n", @@ -152,6 +166,10 @@ TRACE("Re-registered class %s\n", debugstr_w (subclasses[i].className)); } + + if (!DeactivateActCtx(0, ulCookie)) + ERR("DeactivateActCtx failed\n"); + } } Index: win32ss/user/ntuser/class.c =================================================================== --- win32ss/user/ntuser/class.c (revision 73783) +++ win32ss/user/ntuser/class.c (working copy) @@ -2743,6 +2743,7 @@ NULL); if (ClassAtom != (RTL_ATOM)0) { + ClassAtom = Class->atomNVClassName; Ret = UserGetClassInfo(Class, &Safewcexw, bAnsi, hInstance); } else Index: win32ss/user/ntuser/window.c =================================================================== --- win32ss/user/ntuser/window.c (revision 73783) +++ win32ss/user/ntuser/window.c (working copy) @@ -2807,7 +2807,7 @@ /* Do not send WM_GETTEXT messages in the kernel mode version! The user mode version however calls GetWindowText() which will send WM_GETTEXT messages to windows belonging to its processes */ - if (!ClassAtom || Child->pcls->atomClassName == ClassAtom) + if (!ClassAtom || Child->pcls->atomNVClassName == ClassAtom) { // FIXME: LARGE_STRING truncated CurrentWindowName.Buffer = Child->strName.Buffer; @@ -2999,7 +2999,7 @@ (TopLevelWindow->strName.Length < 0xFFFF && !RtlCompareUnicodeString(&WindowName, &ustr, TRUE)); ClassMatches = (ClassAtom == (RTL_ATOM)0) || - ClassAtom == TopLevelWindow->pcls->atomClassName; + ClassAtom == TopLevelWindow->pcls->atomNVClassName; if (WindowMatches && ClassMatches) { Index: win32ss/user/user32/windows/class.c =================================================================== --- win32ss/user/user32/windows/class.c (revision 73783) +++ win32ss/user/user32/windows/class.c (working copy) @@ -13,35 +13,95 @@ #include WINE_DEFAULT_DEBUG_CHANNEL(user32); +#define USE_VERSIONED_CLASSES + /* From rtl/actctx.c and must match! */ -struct entity +struct strsection_header { - DWORD kind; // Activation context type - WCHAR *name; // Class name - WCHAR *clsid; // Not supported yet but needed for menu name. + DWORD magic; + ULONG size; + DWORD unk1[3]; + ULONG count; + ULONG index_offset; + DWORD unk2[2]; + ULONG global_offset; + ULONG global_len; }; -struct dll_redirect +struct wndclass_redirect_data { - WCHAR *name; // Dll name - WCHAR *hash; - DWORD Data; // Junk + ULONG size; + DWORD res; + ULONG name_len; + ULONG name_offset; /* versioned name offset */ + ULONG module_len; + ULONG module_offset;/* container name offset */ }; +// +// Use wine hack to process extened context classes. +// +/*********************************************************************** + * is_comctl32_class + */ +LPCWSTR is_comctl32_class( const WCHAR *name ) +{ + static const WCHAR classesW[][20] = + { + {'C','o','m','b','o','B','o','x','E','x','3','2',0}, + {'m','s','c','t','l','s','_','h','o','t','k','e','y','3','2',0}, + {'m','s','c','t','l','s','_','p','r','o','g','r','e','s','s','3','2',0}, + {'m','s','c','t','l','s','_','s','t','a','t','u','s','b','a','r','3','2',0}, + {'m','s','c','t','l','s','_','t','r','a','c','k','b','a','r','3','2',0}, + {'m','s','c','t','l','s','_','u','p','d','o','w','n','3','2',0}, + {'N','a','t','i','v','e','F','o','n','t','C','t','l',0}, + {'R','e','B','a','r','W','i','n','d','o','w','3','2',0}, + {'S','y','s','A','n','i','m','a','t','e','3','2',0}, + {'S','y','s','D','a','t','e','T','i','m','e','P','i','c','k','3','2',0}, + {'S','y','s','H','e','a','d','e','r','3','2',0}, + {'S','y','s','I','P','A','d','d','r','e','s','s','3','2',0}, + {'S','y','s','L','i','s','t','V','i','e','w','3','2',0}, + {'S','y','s','M','o','n','t','h','C','a','l','3','2',0}, + {'S','y','s','P','a','g','e','r',0}, + {'S','y','s','T','a','b','C','o','n','t','r','o','l','3','2',0}, + {'S','y','s','T','r','e','e','V','i','e','w','3','2',0}, + {'T','o','o','l','b','a','r','W','i','n','d','o','w','3','2',0}, + {'t','o','o','l','t','i','p','s','_','c','l','a','s','s','3','2',0}, + }; + + int min = 0, max = (sizeof(classesW) / sizeof(classesW[0])) - 1; + + while (min <= max) + { + int res, pos = (min + max) / 2; + if (!(res = strcmpiW( name, classesW[pos] ))) return classesW[pos]; + if (res < 0) max = pos - 1; + else min = pos + 1; + } + return NULL; +} + LPCWSTR FASTCALL ClassNameToVersion( - LPCTSTR lpszClass, + const void* lpszClass, LPCWSTR lpszMenuName, LPCWSTR *plpLibFileName, HANDLE *pContext, BOOL bAnsi) { + LPCWSTR VersionedClass = NULL; NTSTATUS Status; UNICODE_STRING SectionName; WCHAR SeactionNameBuf[MAX_PATH] = {0}; ACTCTX_SECTION_KEYED_DATA KeyedData = { sizeof(KeyedData) }; + if(!lpszClass) + { + ERR("Null class given !\n"); + return NULL; + } + if (IS_ATOM(lpszClass)) { SectionName.Buffer = (LPWSTR)&SeactionNameBuf; @@ -48,18 +108,25 @@ SectionName.MaximumLength = sizeof(SeactionNameBuf); if(!NtUserGetAtomName(LOWORD((DWORD_PTR)lpszClass), &SectionName)) { + ERR("Couldn't get atom name for atom %x !\n", LOWORD((DWORD_PTR)lpszClass)); return NULL; } + SectionName.Length = wcslen(SeactionNameBuf) * sizeof(WCHAR); + TRACE("ClassNameToVersion got name %wZ from atom\n", &SectionName); } else { if (bAnsi) { - RtlCreateUnicodeStringFromAsciiz(&SectionName, (LPSTR)lpszClass); + ANSI_STRING AnsiString; + RtlInitAnsiString(&AnsiString, (LPCSTR)lpszClass); + SectionName.Buffer = (LPWSTR)&SeactionNameBuf; + SectionName.MaximumLength = sizeof(SeactionNameBuf); + RtlAnsiStringToUnicodeString(&SectionName, &AnsiString, FALSE); } else { - RtlInitUnicodeString(&SectionName, lpszClass); + RtlInitUnicodeString(&SectionName, (LPCWSTR)lpszClass); } } Status = RtlFindActivationContextSectionString( FIND_ACTCTX_SECTION_KEY_RETURN_HACTCTX, @@ -68,49 +135,57 @@ &SectionName, &KeyedData ); +#ifdef USE_VERSIONED_CLASSES if (NT_SUCCESS(Status) && KeyedData.ulDataFormatVersion == 1) { - struct dll_redirect *dll = KeyedData.lpSectionBase; + struct strsection_header *SectionHeader = KeyedData.lpSectionBase; - if (plpLibFileName) *plpLibFileName = dll->name; - - if (lpszMenuName) + /* Find activation context */ + if(SectionHeader && SectionHeader->count > 0) { - WCHAR * mnubuf; - LPWSTR mnuNameW; - LPSTR mnuNameA; - int len = 0; - struct entity *entity = KeyedData.lpData; + struct wndclass_redirect_data *WindowRedirectionData = KeyedData.lpData; + if(WindowRedirectionData && WindowRedirectionData->module_len) + { + LPCWSTR lpLibFileName; - FIXME("actctx: Needs to support menu name from redirected class!"); + VersionedClass = (WCHAR*)((BYTE*)WindowRedirectionData + WindowRedirectionData->name_offset); + lpLibFileName = (WCHAR*)((BYTE*)KeyedData.lpSectionBase + WindowRedirectionData->module_offset); + TRACE("Returning VersionedClass=%S, plpLibFileName=%S for class %S\n", VersionedClass, lpLibFileName, SectionName.Buffer); - if (entity->clsid) - { - mnubuf = entity->clsid; - if (bAnsi) - { - mnuNameA = (LPSTR)lpszMenuName; - RtlUnicodeToMultiByteN( mnuNameA, 255, (PULONG)&len, mnubuf, strlenW(mnubuf) * sizeof(WCHAR) ); - mnuNameA[len] = 0; - } - else - { - mnuNameW = (LPWSTR)lpszMenuName; - len = strlenW(mnubuf) * sizeof(WCHAR); - RtlCopyMemory((void *)mnuNameW, mnubuf, len); - mnuNameW[len] = 0; - } + if (pContext) *pContext = KeyedData.hActCtx; + if (plpLibFileName) *plpLibFileName = lpLibFileName; + } } - if (pContext) *pContext = KeyedData.hActCtx; } - if (!IS_ATOM(lpszClass) && bAnsi) - RtlFreeUnicodeString(&SectionName); if (KeyedData.hActCtx) RtlReleaseActivationContext(KeyedData.hActCtx); +#endif - return lpszClass; +#ifndef DEFAULT_ACTIVATION_CONTEXTS_SUPPORTED + /* This block is a hack! */ + if (!VersionedClass) + { + /* + * In windows the default activation context always contains comctl32v5 + * In reactos we don't have a default activation context so we + * mimic wine here. + */ + VersionedClass = is_comctl32_class(SectionName.Buffer); + if (VersionedClass) + { + if (pContext) *pContext = 0; + if (plpLibFileName) *plpLibFileName = L"comctl32"; + } + } +#endif + + /* + * The returned strings are pointers in the activation context and + * will get freed when the activation context gets freed + */ + return VersionedClass; } // @@ -118,14 +193,14 @@ // BOOL FASTCALL -Real_VersionRegisterClass( +VersionRegisterClass( PCWSTR pszClass, LPCWSTR lpLibFileName, HANDLE Contex, HMODULE * phLibModule) { - BOOL Ret; - HMODULE hLibModule; + BOOL Ret = FALSE; + HMODULE hLibModule = NULL; PREGISTERCLASSNAMEW pRegisterClassNameW; UNICODE_STRING ClassName; WCHAR ClassNameBuf[MAX_PATH] = {0}; @@ -133,9 +208,6 @@ RtlActivateActivationContextUnsafeFast(&Frame, Contex); - Ret = FALSE; - hLibModule = NULL; - _SEH2_TRY { hLibModule = LoadLibraryW(lpLibFileName); @@ -145,16 +217,21 @@ { if (IS_ATOM(pszClass)) { - ClassName.Buffer = (LPWSTR)&ClassNameBuf; + ClassName.Buffer = ClassNameBuf; ClassName.MaximumLength = sizeof(ClassNameBuf); if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName)) { + ERR("Error while verifying ATOM\n"); _SEH2_YIELD(goto Error_Exit); } - pszClass = (PCWSTR)&ClassNameBuf; + pszClass = ClassName.Buffer; } Ret = pRegisterClassNameW(pszClass); } + else + { + WARN("No RegisterClassNameW PROC\n"); + } } } _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) @@ -174,119 +251,10 @@ SetLastError(save_error); } + RtlDeactivateActivationContextUnsafeFast(&Frame); return Ret; } -// -// Use wine hack to process extened context classes. -// -/*********************************************************************** - * is_comctl32_class - */ -static BOOL is_comctl32_class( const WCHAR *name ) -{ - static const WCHAR classesW[][20] = - { - {'C','o','m','b','o','B','o','x','E','x','3','2',0}, - {'m','s','c','t','l','s','_','h','o','t','k','e','y','3','2',0}, - {'m','s','c','t','l','s','_','p','r','o','g','r','e','s','s','3','2',0}, - {'m','s','c','t','l','s','_','s','t','a','t','u','s','b','a','r','3','2',0}, - {'m','s','c','t','l','s','_','t','r','a','c','k','b','a','r','3','2',0}, - {'m','s','c','t','l','s','_','u','p','d','o','w','n','3','2',0}, - {'N','a','t','i','v','e','F','o','n','t','C','t','l',0}, - {'R','e','B','a','r','W','i','n','d','o','w','3','2',0}, - {'S','y','s','A','n','i','m','a','t','e','3','2',0}, - {'S','y','s','D','a','t','e','T','i','m','e','P','i','c','k','3','2',0}, - {'S','y','s','H','e','a','d','e','r','3','2',0}, - {'S','y','s','I','P','A','d','d','r','e','s','s','3','2',0}, - {'S','y','s','L','i','s','t','V','i','e','w','3','2',0}, - {'S','y','s','M','o','n','t','h','C','a','l','3','2',0}, - {'S','y','s','P','a','g','e','r',0}, - {'S','y','s','T','a','b','C','o','n','t','r','o','l','3','2',0}, - {'S','y','s','T','r','e','e','V','i','e','w','3','2',0}, - {'T','o','o','l','b','a','r','W','i','n','d','o','w','3','2',0}, - {'t','o','o','l','t','i','p','s','_','c','l','a','s','s','3','2',0}, - }; - - int min = 0, max = (sizeof(classesW) / sizeof(classesW[0])) - 1; - - while (min <= max) - { - int res, pos = (min + max) / 2; - if (!(res = strcmpiW( name, classesW[pos] ))) return TRUE; - if (res < 0) max = pos - 1; - else min = pos + 1; - } - return FALSE; -} - -BOOL -FASTCALL -VersionRegisterClass( - PCWSTR pszClass, - LPCWSTR lpLibFileName, - HANDLE Contex, - HMODULE * phLibModule) -{ - // Should be lpLibFileName..... - static const WCHAR comctl32W[] = {'c','o','m','c','t','l','3','2','.','d','l','l',0}; - // - PREGISTERCLASSNAMEW pRegisterClassNameW; - UNICODE_STRING ClassName; - WCHAR ClassNameBuf[MAX_PATH] = {0}; - BOOL Ret = FALSE; - HMODULE hLibModule = NULL; - - if (!IS_ATOM(pszClass) && is_comctl32_class( pszClass )) - { - _SEH2_TRY - { - hLibModule = LoadLibraryW(comctl32W); - if ( hLibModule ) - { - if ((pRegisterClassNameW = (void*) GetProcAddress(hLibModule, "RegisterClassNameW"))) - { - if (IS_ATOM(pszClass)) - { - ClassName.Buffer = (LPWSTR)&ClassNameBuf; - ClassName.MaximumLength = sizeof(ClassNameBuf); - if (!NtUserGetAtomName(LOWORD((DWORD_PTR)pszClass), &ClassName)) - { - ERR("Error while verifying ATOM\n"); - _SEH2_YIELD(goto Error_Exit); - } - pszClass = (PCWSTR)&ClassNameBuf; - } - Ret = pRegisterClassNameW(pszClass); - } - } - } - _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER) - { - } - _SEH2_END - -Error_Exit: - if ( Ret || !hLibModule ) - { - if ( phLibModule ) *phLibModule = hLibModule; - } - else - { - DWORD save_error = GetLastError(); - FreeLibrary(hLibModule); - SetLastError(save_error); - } - TRACE( "%s retrying after loading comctl32\n", debugstr_w(pszClass) ); - return Ret; - } - TRACE("NO ComCtl32 Class %S!\n",pszClass); - return FALSE; -} -// -// -// - /* * @implemented */ @@ -301,7 +269,10 @@ LPCSTR pszMenuName; HMODULE hLibModule = NULL; DWORD save_error; - BOOL Ret, ClassFound = FALSE; + BOOL Ret, ClassFound = FALSE, ConvertedString = FALSE; + LPCWSTR lpszClsVersion; + HANDLE pCtx = NULL; + LPCWSTR lpLibFileName = NULL; TRACE("%p class/atom: %s/%04x %p\n", hInstance, IS_ATOM(lpszClass) ? NULL : lpszClass, @@ -325,14 +296,19 @@ return FALSE; } - if (IS_ATOM(lpszClass)) + lpszClsVersion = ClassNameToVersion(lpszClass, NULL, &lpLibFileName, &pCtx, TRUE); + if (lpszClsVersion) { + RtlInitUnicodeString(&ClassName, lpszClsVersion); + } + else if (IS_ATOM(lpszClass)) + { ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass); } else { - if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, - lpszClass)) + ConvertedString = TRUE; + if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, lpszClass)) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return FALSE; @@ -353,6 +329,7 @@ (LPWSTR *)&pszMenuName, TRUE); if (Ret) break; + if (!lpLibFileName) break; if (!ClassFound) { save_error = GetLastError(); @@ -359,7 +336,7 @@ if ( save_error == ERROR_CANNOT_FIND_WND_CLASS || save_error == ERROR_CLASS_DOES_NOT_EXIST ) { - ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); + ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule); if (ClassFound) continue; } } @@ -379,7 +356,7 @@ // lpwcx->lpszMenuName = pszMenuName; } - if (!IS_ATOM(lpszClass)) + if (ConvertedString) { RtlFreeUnicodeString(&ClassName); } @@ -403,6 +380,9 @@ HMODULE hLibModule = NULL; DWORD save_error; BOOL Ret, ClassFound = FALSE; + LPCWSTR lpszClsVersion; + HANDLE pCtx = NULL; + LPCWSTR lpLibFileName = NULL; TRACE("%p class/atom: %S/%04x %p\n", hInstance, IS_ATOM(lpszClass) ? NULL : lpszClass, @@ -429,14 +409,18 @@ return FALSE; } - if (IS_ATOM(lpszClass)) + lpszClsVersion = ClassNameToVersion(lpszClass, NULL, &lpLibFileName, &pCtx, FALSE); + if (lpszClsVersion) { + RtlInitUnicodeString(&ClassName, lpszClsVersion); + } + else if (IS_ATOM(lpszClass)) + { ClassName.Buffer = (PWSTR)((ULONG_PTR)lpszClass); } else { - RtlInitUnicodeString(&ClassName, - lpszClass); + RtlInitUnicodeString(&ClassName, lpszClass); } if (!RegisterDefaultClasses) @@ -453,6 +437,7 @@ &pszMenuName, FALSE); if (Ret) break; + if (!lpLibFileName) break; if (!ClassFound) { save_error = GetLastError(); @@ -459,7 +444,7 @@ if ( save_error == ERROR_CANNOT_FIND_WND_CLASS || save_error == ERROR_CLASS_DOES_NOT_EXIST ) { - ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); + ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule); if (ClassFound) continue; } } @@ -1419,12 +1404,11 @@ ATOM Atom; WNDCLASSEXW WndClass; UNICODE_STRING ClassName; + UNICODE_STRING ClassVersion; UNICODE_STRING MenuName = {0}; CLSMENUNAME clsMenuName; ANSI_STRING AnsiMenuName; - HMODULE hLibModule = NULL; - DWORD save_error; - BOOL ClassFound = FALSE; + LPCWSTR lpszClsVersion; if (lpwcx == NULL || lpwcx->cbSize != sizeof(WNDCLASSEXW) || lpwcx->cbClsExtra < 0 || lpwcx->cbWndExtra < 0 || @@ -1495,41 +1479,28 @@ RtlInitUnicodeString(&ClassName, WndClass.lpszClassName); } + ClassVersion = ClassName; + if (fnID == 0) + { + lpszClsVersion = ClassNameToVersion(lpwcx->lpszClassName, NULL, NULL, NULL, FALSE); + if (lpszClsVersion) + { + RtlInitUnicodeString(&ClassVersion, lpszClsVersion); + } + } + clsMenuName.pszClientAnsiMenuName = AnsiMenuName.Buffer; clsMenuName.pwszClientUnicodeMenuName = MenuName.Buffer; clsMenuName.pusMenuName = &MenuName; - for(;;) - { - Atom = NtUserRegisterClassExWOW( &WndClass, - &ClassName, - &ClassName, //PUNICODE_STRING ClsNVersion, - &clsMenuName, - fnID, - dwFlags, - pdwWowData); + Atom = NtUserRegisterClassExWOW( &WndClass, + &ClassName, + &ClassVersion, + &clsMenuName, + fnID, + dwFlags, + pdwWowData); - if (Atom) break; - if (!ClassFound) - { - save_error = GetLastError(); - if ( save_error == ERROR_CANNOT_FIND_WND_CLASS || - save_error == ERROR_CLASS_DOES_NOT_EXIST ) - { - ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); - if (ClassFound) continue; - } - } - if (hLibModule) - { - save_error = GetLastError(); - FreeLibrary(hLibModule); - SetLastError(save_error); - hLibModule = 0; - } - break; - } - TRACE("atom=%04x wndproc=%p hinst=%p bg=%p style=%08x clsExt=%d winExt=%d class=%p\n", Atom, lpwcx->lpfnWndProc, lpwcx->hInstance, lpwcx->hbrBackground, lpwcx->style, lpwcx->cbClsExtra, lpwcx->cbWndExtra, WndClass); @@ -1886,6 +1857,8 @@ { UNICODE_STRING ClassName = {0}; BOOL Ret; + LPCWSTR lpszClsVersion; + BOOL ConvertedString = FALSE; TRACE("class/atom: %s/%04x %p\n", IS_ATOM(lpClassName) ? NULL : lpClassName, @@ -1892,10 +1865,15 @@ IS_ATOM(lpClassName) ? lpClassName : 0, hInstance); - if (!IS_ATOM(lpClassName)) + lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, TRUE); + if (lpszClsVersion) { - if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, - lpClassName)) + RtlInitUnicodeString(&ClassName, lpszClsVersion); + } + else if (!IS_ATOM(lpClassName)) + { + ConvertedString = TRUE; + if (!RtlCreateUnicodeStringFromAsciiz(&ClassName, lpClassName)) { SetLastError(ERROR_NOT_ENOUGH_MEMORY); return 0; @@ -1904,11 +1882,9 @@ else ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); - Ret = NtUserUnregisterClass(&ClassName, - hInstance, - 0); + Ret = NtUserUnregisterClass(&ClassName, hInstance, 0); - if (!IS_ATOM(lpClassName)) + if (ConvertedString) RtlFreeUnicodeString(&ClassName); return Ret; @@ -1925,6 +1901,7 @@ HINSTANCE hInstance) { UNICODE_STRING ClassName = {0}; + LPCWSTR lpszClsVersion; TRACE("class/atom: %S/%04x %p\n", IS_ATOM(lpClassName) ? NULL : lpClassName, @@ -1931,17 +1908,21 @@ IS_ATOM(lpClassName) ? lpClassName : 0, hInstance); - if (!IS_ATOM(lpClassName)) + lpszClsVersion = ClassNameToVersion(lpClassName, NULL, NULL, NULL, FALSE); + if (lpszClsVersion) { - RtlInitUnicodeString(&ClassName, - lpClassName); + RtlInitUnicodeString(&ClassName, lpszClsVersion); } + else if (!IS_ATOM(lpClassName)) + { + RtlInitUnicodeString(&ClassName, lpClassName); + } else + { ClassName.Buffer = (PWSTR)((ULONG_PTR)lpClassName); + } - return NtUserUnregisterClass(&ClassName, - hInstance, - 0); + return NtUserUnregisterClass(&ClassName, hInstance, 0); } /* EOF */ Index: win32ss/user/user32/windows/window.c =================================================================== --- win32ss/user/user32/windows/window.c (revision 73783) +++ win32ss/user/user32/windows/window.c (working copy) @@ -16,6 +16,7 @@ WINE_DEFAULT_DEBUG_CHANNEL(user32); void MDI_CalcDefaultChildPos( HWND hwndClient, INT total, LPPOINT lpPos, INT delta, UINT *id ); +extern LPCWSTR FASTCALL ClassNameToVersion(const void *lpszClass, LPCWSTR lpszMenuName, LPCWSTR *plpLibFileName, HANDLE *pContext, BOOL bAnsi); /* FUNCTIONS *****************************************************************/ @@ -165,7 +166,9 @@ { LARGE_STRING WindowName; LARGE_STRING lstrClassName, *plstrClassName; + LARGE_STRING lstrClassVersion, *plstrClassVersion; UNICODE_STRING ClassName; + UNICODE_STRING ClassVersion; WNDCLASSEXA wceA; WNDCLASSEXW wceW; HMODULE hLibModule = NULL; @@ -172,6 +175,9 @@ DWORD save_error; BOOL Unicode, ClassFound = FALSE; HWND Handle = NULL; + LPCWSTR lpszClsVersion; + HANDLE pCtx; + LPCWSTR lpLibFileName; #if 0 DbgPrint("[window] User32CreateWindowEx style %d, exstyle %d, parent %d\n", dwStyle, dwExStyle, hWndParent); @@ -263,11 +269,25 @@ if (!Unicode) dwExStyle |= WS_EX_SETANSICREATOR; + lpszClsVersion = ClassNameToVersion(lpClassName, NULL, &lpLibFileName, &pCtx, !Unicode); + if (!lpszClsVersion) + { + plstrClassVersion = plstrClassName; + } + else + { + RtlInitUnicodeString(&ClassVersion, lpszClsVersion); + lstrClassVersion.Buffer = ClassVersion.Buffer; + lstrClassVersion.Length = ClassVersion.Length; + lstrClassVersion.MaximumLength = ClassVersion.MaximumLength; + plstrClassVersion = &lstrClassVersion; + } + for(;;) { Handle = NtUserCreateWindowEx(dwExStyle, plstrClassName, - plstrClassName, + plstrClassVersion, &WindowName, dwStyle, x, @@ -281,12 +301,13 @@ dwFlags, NULL); if (Handle) break; + if (!lpLibFileName) break; if (!ClassFound) { save_error = GetLastError(); if ( save_error == ERROR_CANNOT_FIND_WND_CLASS ) { - ClassFound = VersionRegisterClass(ClassName.Buffer, NULL, NULL, &hLibModule); + ClassFound = VersionRegisterClass(ClassName.Buffer, lpLibFileName, pCtx, &hLibModule); if (ClassFound) continue; } }