[uxtheme]

- Fix almost all of the (few) tests for uxtheme
- Do not allow opening or enumerating themes when the themes service is not running

svn path=/trunk/; revision=59098
This commit is contained in:
Giannis Adamopoulos 2013-05-28 19:19:29 +00:00
parent bcb4136c3a
commit 7791dc4bd9
4 changed files with 93 additions and 39 deletions

View file

@ -81,6 +81,9 @@ HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWST
LPWSTR pszSelectedSize = NULL; LPWSTR pszSelectedSize = NULL;
LPWSTR tmp; LPWSTR tmp;
if (!gbThemeHooksActive)
return E_FAIL;
TRACE("Opening %s\n", debugstr_w(lpThemeFile)); TRACE("Opening %s\n", debugstr_w(lpThemeFile));
hTheme = LoadLibraryExW(lpThemeFile, NULL, LOAD_LIBRARY_AS_DATAFILE); hTheme = LoadLibraryExW(lpThemeFile, NULL, LOAD_LIBRARY_AS_DATAFILE);
@ -168,6 +171,9 @@ HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWST
(*tf)->pszSelectedColor = pszSelectedColor; (*tf)->pszSelectedColor = pszSelectedColor;
(*tf)->pszSelectedSize = pszSelectedSize; (*tf)->pszSelectedSize = pszSelectedSize;
(*tf)->dwRefCount = 1; (*tf)->dwRefCount = 1;
TRACE("Theme %p refcount: %d\n", *tf, (*tf)->dwRefCount);
return S_OK; return S_OK;
invalid_theme: invalid_theme:
@ -183,7 +189,10 @@ invalid_theme:
void MSSTYLES_CloseThemeFile(PTHEME_FILE tf) void MSSTYLES_CloseThemeFile(PTHEME_FILE tf)
{ {
if(tf) { if(tf) {
tf->dwRefCount--; tf->dwRefCount--;
TRACE("Theme %p refcount: %d\n", tf, tf->dwRefCount);
if(!tf->dwRefCount) { if(!tf->dwRefCount) {
if(tf->hTheme) FreeLibrary(tf->hTheme); if(tf->hTheme) FreeLibrary(tf->hTheme);
if(tf->classes) { if(tf->classes) {
@ -218,6 +227,7 @@ void MSSTYLES_CloseThemeFile(PTHEME_FILE tf)
HRESULT MSSTYLES_ReferenceTheme(PTHEME_FILE tf) HRESULT MSSTYLES_ReferenceTheme(PTHEME_FILE tf)
{ {
tf->dwRefCount++; tf->dwRefCount++;
TRACE("Theme %p refcount: %d\n", tf, tf->dwRefCount);
return S_OK; return S_OK;
} }
@ -774,6 +784,7 @@ PTHEME_CLASS MSSTYLES_OpenThemeClass(PTHEME_FILE tf, LPCWSTR pszAppName, LPCWSTR
TRACE("Opened app %s, class %s from list %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName), debugstr_w(pszClassList)); TRACE("Opened app %s, class %s from list %s\n", debugstr_w(cls->szAppName), debugstr_w(cls->szClassName), debugstr_w(pszClassList));
cls->tf = tf; cls->tf = tf;
cls->tf->dwRefCount++; cls->tf->dwRefCount++;
TRACE("Theme %p refcount: %d\n", tf, tf->dwRefCount);
} }
return cls; return cls;
} }

View file

@ -50,8 +50,6 @@ static ATOM atSubAppName;
static ATOM atSubIdList; static ATOM atSubIdList;
ATOM atWndContrext; ATOM atWndContrext;
static BOOL bThemeActive = FALSE;
static PTHEME_FILE ActiveThemeFile; static PTHEME_FILE ActiveThemeFile;
/***********************************************************************/ /***********************************************************************/
@ -155,6 +153,7 @@ void UXTHEME_LoadTheme(BOOL bLoad)
WCHAR szCurrentTheme[MAX_PATH]; WCHAR szCurrentTheme[MAX_PATH];
WCHAR szCurrentColor[64]; WCHAR szCurrentColor[64];
WCHAR szCurrentSize[64]; WCHAR szCurrentSize[64];
BOOL bThemeActive = FALSE;
if(bLoad == TRUE) if(bLoad == TRUE)
{ {
@ -472,24 +471,26 @@ static HRESULT UXTHEME_ApplyTheme(PTHEME_FILE tf)
WCHAR tmp[2]; WCHAR tmp[2];
HRESULT hr; HRESULT hr;
if(tf && !bThemeActive) UXTHEME_BackupSystemMetrics(); if (tf && !ActiveThemeFile)
hr = UXTHEME_SetActiveTheme(tf); {
if(FAILED(hr)) UXTHEME_BackupSystemMetrics();
return hr;
if(tf) {
bThemeActive = TRUE;
} }
else {
hr = UXTHEME_SetActiveTheme(tf);
if (FAILED(hr))
return hr;
if (!tf)
{
UXTHEME_RestoreSystemMetrics(); UXTHEME_RestoreSystemMetrics();
bThemeActive = FALSE;
} }
TRACE("Writing theme config to registry\n"); TRACE("Writing theme config to registry\n");
if(!RegCreateKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) { if(!RegCreateKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
tmp[0] = bThemeActive?'1':'0'; tmp[0] = ActiveThemeFile?'1':'0';
tmp[1] = '\0'; tmp[1] = '\0';
RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (const BYTE*)tmp, sizeof(WCHAR)*2); RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (const BYTE*)tmp, sizeof(WCHAR)*2);
if(bThemeActive) { if (ActiveThemeFile) {
RegSetValueExW(hKey, szColorName, 0, REG_SZ, (const BYTE*)tf->pszSelectedColor, RegSetValueExW(hKey, szColorName, 0, REG_SZ, (const BYTE*)tf->pszSelectedColor,
(lstrlenW(tf->pszSelectedColor)+1)*sizeof(WCHAR)); (lstrlenW(tf->pszSelectedColor)+1)*sizeof(WCHAR));
RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const BYTE*)tf->pszSelectedSize, RegSetValueExW(hKey, szSizeName, 0, REG_SZ, (const BYTE*)tf->pszSelectedSize,
@ -545,7 +546,9 @@ void UXTHEME_InitSystem(HINSTANCE hInst)
*/ */
BOOL WINAPI IsAppThemed(void) BOOL WINAPI IsAppThemed(void)
{ {
return IsThemeActive(); TRACE("\n");
SetLastError(ERROR_SUCCESS);
return (ActiveThemeFile != NULL);
} }
/*********************************************************************** /***********************************************************************
@ -553,9 +556,32 @@ BOOL WINAPI IsAppThemed(void)
*/ */
BOOL WINAPI IsThemeActive(void) BOOL WINAPI IsThemeActive(void)
{ {
BOOL bActive;
LRESULT Result;
HKEY hKey;
WCHAR tmp[10];
DWORD buffsize;
TRACE("\n"); TRACE("\n");
SetLastError(ERROR_SUCCESS); SetLastError(ERROR_SUCCESS);
return bThemeActive;
if (ActiveThemeFile)
return TRUE;
if (gbThemeHooksActive)
return FALSE;
bActive = FALSE;
Result = RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey);
if (Result == ERROR_SUCCESS)
{
buffsize = sizeof(tmp)/sizeof(tmp[0]);
if (!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize))
bActive = (tmp[0] != '0');
RegCloseKey(hKey);
}
return bActive;
} }
/*********************************************************************** /***********************************************************************
@ -571,14 +597,14 @@ HRESULT WINAPI EnableTheming(BOOL fEnable)
TRACE("(%d)\n", fEnable); TRACE("(%d)\n", fEnable);
if(fEnable != bThemeActive) { if (fEnable != (ActiveThemeFile != NULL)) {
if(fEnable) if(fEnable)
UXTHEME_BackupSystemMetrics(); UXTHEME_BackupSystemMetrics();
else else
UXTHEME_RestoreSystemMetrics(); UXTHEME_RestoreSystemMetrics();
UXTHEME_SaveSystemMetrics (); UXTHEME_SaveSystemMetrics ();
bThemeActive = fEnable;
if(bThemeActive) szEnabled[0] = '1'; if (fEnable) szEnabled[0] = '1';
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) { if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (LPBYTE)szEnabled, sizeof(WCHAR)); RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (LPBYTE)szEnabled, sizeof(WCHAR));
RegCloseKey(hKey); RegCloseKey(hKey);
@ -641,7 +667,7 @@ OpenThemeDataInternal(PTHEME_FILE ThemeFile, HWND hwnd, LPCWSTR pszClassList, DW
if(flags) if(flags)
FIXME("unhandled flags: %x\n", flags); FIXME("unhandled flags: %x\n", flags);
if(bThemeActive) if (ThemeFile)
{ {
pszAppName = UXTHEME_GetWindowProperty(hwnd, atSubAppName, szAppBuff, sizeof(szAppBuff)/sizeof(szAppBuff[0])); pszAppName = UXTHEME_GetWindowProperty(hwnd, atSubAppName, szAppBuff, sizeof(szAppBuff)/sizeof(szAppBuff[0]));
/* If SetWindowTheme was used on the window, that overrides the class list passed to this function */ /* If SetWindowTheme was used on the window, that overrides the class list passed to this function */
@ -650,10 +676,24 @@ OpenThemeDataInternal(PTHEME_FILE ThemeFile, HWND hwnd, LPCWSTR pszClassList, DW
pszUseClassList = pszClassList; pszUseClassList = pszClassList;
if (pszUseClassList) if (pszUseClassList)
{
if (!ThemeFile->classes)
MSSTYLES_ParseThemeIni(ThemeFile);
hTheme = MSSTYLES_OpenThemeClass(ThemeFile, pszAppName, pszUseClassList); hTheme = MSSTYLES_OpenThemeClass(ThemeFile, pszAppName, pszUseClassList);
}
} }
if(IsWindow(hwnd)) if(IsWindow(hwnd))
{
SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atWindowTheme), hTheme); SetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atWindowTheme), hTheme);
}
else
{
SetLastError(E_PROP_ID_UNSUPPORTED);
}
SetLastError(hTheme ? ERROR_SUCCESS : E_PROP_ID_UNSUPPORTED);
TRACE(" = %p\n", hTheme); TRACE(" = %p\n", hTheme);
return hTheme; return hTheme;
} }
@ -667,15 +707,11 @@ HTHEME WINAPI OpenThemeDataEx(HWND hwnd, LPCWSTR pszClassList, DWORD flags)
} }
/*********************************************************************** /***********************************************************************
* OpenThemeDataEx (UXTHEME.16) * OpenThemeDataFromFile (UXTHEME.16)
*/ */
HTHEME WINAPI OpenThemeDataFromFile(HTHEMEFILE hThemeFile, HWND hwnd, LPCWSTR pszClassList, DWORD flags) HTHEME WINAPI OpenThemeDataFromFile(HTHEMEFILE hThemeFile, HWND hwnd, LPCWSTR pszClassList, DWORD flags)
{ {
PTHEME_FILE ThemeFile = (PTHEME_FILE)hThemeFile; return OpenThemeDataInternal((PTHEME_FILE)hThemeFile, hwnd, pszClassList, flags);
MSSTYLES_ParseThemeIni(ThemeFile);
return OpenThemeDataInternal(ThemeFile, hwnd, pszClassList, flags);
} }
/*********************************************************************** /***********************************************************************
@ -700,8 +736,12 @@ HTHEME WINAPI OpenThemeData(HWND hwnd, LPCWSTR classlist)
HTHEME WINAPI GetWindowTheme(HWND hwnd) HTHEME WINAPI GetWindowTheme(HWND hwnd)
{ {
TRACE("(%p)\n", hwnd); TRACE("(%p)\n", hwnd);
if(!IsWindow(hwnd)) if(!IsWindow(hwnd))
{
SetLastError(E_HANDLE); SetLastError(E_HANDLE);
return NULL;
}
return GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atWindowTheme)); return GetPropW(hwnd, (LPCWSTR)MAKEINTATOM(atWindowTheme));
} }
@ -719,12 +759,16 @@ HRESULT WINAPI SetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName,
debugstr_w(pszSubIdList)); debugstr_w(pszSubIdList));
if(!IsWindow(hwnd)) if(!IsWindow(hwnd))
return E_HANDLE; return E_HANDLE;
hr = UXTHEME_SetWindowProperty(hwnd, atSubAppName, pszSubAppName); hr = UXTHEME_SetWindowProperty(hwnd, atSubAppName, pszSubAppName);
if(SUCCEEDED(hr)) if (!SUCCEEDED(hr))
hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList); return hr;
if(SUCCEEDED(hr))
hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList);
if (!SUCCEEDED(hr))
return hr;
UXTHEME_broadcast_msg (hwnd, WM_THEMECHANGED); UXTHEME_broadcast_msg (hwnd, WM_THEMECHANGED);
return hr; return hr;
} }
@ -741,7 +785,7 @@ HRESULT WINAPI GetCurrentThemeName(LPWSTR pszThemeFileName, int dwMaxNameChars,
if(ActiveThemeFile == NULL) if(ActiveThemeFile == NULL)
return E_PROP_ID_UNSUPPORTED; return E_PROP_ID_UNSUPPORTED;
if(pszThemeFileName) if (pszThemeFileName && dwMaxNameChars)
{ {
cchar = lstrlenW(ActiveThemeFile->szThemeFile) + 1; cchar = lstrlenW(ActiveThemeFile->szThemeFile) + 1;
if(cchar > dwMaxNameChars) if(cchar > dwMaxNameChars)
@ -749,7 +793,7 @@ HRESULT WINAPI GetCurrentThemeName(LPWSTR pszThemeFileName, int dwMaxNameChars,
lstrcpynW(pszThemeFileName, ActiveThemeFile->szThemeFile, cchar); lstrcpynW(pszThemeFileName, ActiveThemeFile->szThemeFile, cchar);
} }
if(pszColorBuff) if (pszColorBuff && cchMaxColorChars)
{ {
cchar = lstrlenW(ActiveThemeFile->pszSelectedColor) + 1; cchar = lstrlenW(ActiveThemeFile->pszSelectedColor) + 1;
if(cchar > cchMaxColorChars) if(cchar > cchMaxColorChars)
@ -757,7 +801,7 @@ HRESULT WINAPI GetCurrentThemeName(LPWSTR pszThemeFileName, int dwMaxNameChars,
lstrcpynW(pszColorBuff, ActiveThemeFile->pszSelectedColor, cchar); lstrcpynW(pszColorBuff, ActiveThemeFile->pszSelectedColor, cchar);
} }
if(pszSizeBuff) if (pszSizeBuff && cchMaxSizeChars)
{ {
cchar = lstrlenW(ActiveThemeFile->pszSelectedSize) + 1; cchar = lstrlenW(ActiveThemeFile->pszSelectedSize) + 1;
if(cchar > cchMaxSizeChars) if(cchar > cchMaxSizeChars)

View file

@ -11,16 +11,10 @@
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme); WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
extern HINSTANCE hDllInst;
LRESULT CALLBACK ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc);
USERAPIHOOK user32ApiHook; USERAPIHOOK user32ApiHook;
BYTE gabDWPmessages[UAHOWP_MAX_SIZE]; BYTE gabDWPmessages[UAHOWP_MAX_SIZE];
BYTE gabMSGPmessages[UAHOWP_MAX_SIZE]; BYTE gabMSGPmessages[UAHOWP_MAX_SIZE];
BOOL gbThemeHooksActive = FALSE;
PWND_CONTEXT ThemeGetWndContext(HWND hWnd) PWND_CONTEXT ThemeGetWndContext(HWND hWnd)
{ {
@ -266,14 +260,16 @@ int WINAPI ThemeSetWindowRgn(HWND hWnd, HRGN hRgn, BOOL bRedraw)
BOOL CALLBACK BOOL CALLBACK
ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah) ThemeInitApiHook(UAPIHK State, PUSERAPIHOOK puah)
{ {
/* Sanity checks for the caller */
if (!puah || State != uahLoadInit) if (!puah || State != uahLoadInit)
{ {
UXTHEME_LoadTheme(FALSE); UXTHEME_LoadTheme(FALSE);
ThemeCleanupWndContext(NULL, 0); ThemeCleanupWndContext(NULL, 0);
gbThemeHooksActive = FALSE;
return TRUE; return TRUE;
} }
gbThemeHooksActive = TRUE;
/* Store the original functions from user32 */ /* Store the original functions from user32 */
user32ApiHook = *puah; user32ApiHook = *puah;

View file

@ -199,14 +199,17 @@ enum SCROLL_HITTEST
/* Minimum size of the rectangle between the arrows */ /* Minimum size of the rectangle between the arrows */
#define SCROLL_MIN_RECT 4 #define SCROLL_MIN_RECT 4
LRESULT CALLBACK ThemeWndProc(HWND hWnd, UINT Msg, WPARAM wParam, LPARAM lParam, WNDPROC DefWndProc);
void ThemeDrawScrollBar(PDRAW_CONTEXT pcontext, INT Bar, POINT* pt); void ThemeDrawScrollBar(PDRAW_CONTEXT pcontext, INT Bar, POINT* pt);
VOID NC_TrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt); VOID NC_TrackScrollBar(HWND Wnd, WPARAM wParam, POINT Pt);
void ThemeInitDrawContext(PDRAW_CONTEXT pcontext, HWND hWnd, HRGN hRgn); void ThemeInitDrawContext(PDRAW_CONTEXT pcontext, HWND hWnd, HRGN hRgn);
void ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext); void ThemeCleanupDrawContext(PDRAW_CONTEXT pcontext);
PWND_CONTEXT ThemeGetWndContext(HWND hWnd); PWND_CONTEXT ThemeGetWndContext(HWND hWnd);
extern HINSTANCE hDllInst;
extern ATOM atWindowTheme; extern ATOM atWindowTheme;
extern ATOM atWndContrext; extern ATOM atWndContrext;
extern BOOL gbThemeHooksActive;
void UXTHEME_InitSystem(HINSTANCE hInst); void UXTHEME_InitSystem(HINSTANCE hInst);
void UXTHEME_LoadTheme(BOOL bLoad); void UXTHEME_LoadTheme(BOOL bLoad);