Load, validate and retrieve a few properties from an msstyles theme.

This commit is contained in:
Kevin Koltzau 2003-12-08 22:45:26 +00:00 committed by Alexandre Julliard
parent cc8c205adb
commit d2c4cf14f8
4 changed files with 386 additions and 21 deletions

View File

@ -3,13 +3,14 @@ TOPOBJDIR = ../..
SRCDIR = @srcdir@ SRCDIR = @srcdir@
VPATH = @srcdir@ VPATH = @srcdir@
MODULE = uxtheme.dll MODULE = uxtheme.dll
IMPORTS = gdi32 user32 advapi32 kernel32 ntdll IMPORTS = shlwapi user32 gdi32 advapi32 kernel32 ntdll
EXTRALIBS = $(LIBUNICODE) EXTRALIBS = $(LIBUNICODE)
C_SRCS = \ C_SRCS = \
draw.c \ draw.c \
main.c \ main.c \
metric.c \ metric.c \
msstyles.c \
property.c \ property.c \
system.c system.c

172
dlls/uxtheme/msstyles.c Normal file
View File

@ -0,0 +1,172 @@
/*
* Win32 5.1 msstyles theme format
*
* Copyright (C) 2003 Kevin Koltzau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#include "config.h"
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winuser.h"
#include "wingdi.h"
#include "uxtheme.h"
#include "uxthemedll.h"
#include "msstyles.h"
#include "wine/debug.h"
WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
#define MSSTYLES_VERSION 0x0003
/**********************************************************************
* MSSTYLES_OpenThemeFile
*
* Load and validate a theme
*
* PARAMS
* lpThemeFile Path to theme file to load
* pszColorName Color name wanted, can be NULL
* pszSizeName Size name wanted, can be NULL
*
* NOTES
* If pszColorName or pszSizeName are NULL, the default color/size will be used.
* If one/both are provided, they are validated against valid color/sizes and if
* a match is not found, the function fails.
*/
HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWSTR pszSizeName, PTHEME_FILE *tf)
{
HMODULE hTheme;
HRSRC hrsc;
HRESULT hr = S_OK;
WCHAR szPackThemVersionResource[] = {
'P','A','C','K','T','H','E','M','_','V','E','R','S','I','O','N', '\0'
};
WCHAR szColorNamesResource[] = {
'C','O','L','O','R','N','A','M','E','S','\0'
};
WCHAR szSizeNamesResource[] = {
'S','I','Z','E','N','A','M','E','S','\0'
};
WORD version;
DWORD versize;
LPWSTR pszColors;
LPWSTR pszSelectedColor = NULL;
LPWSTR pszSizes;
LPWSTR pszSelectedSize = NULL;
LPWSTR tmp;
TRACE("Opening %s\n", debugstr_w(lpThemeFile));
hTheme = LoadLibraryExW(lpThemeFile, NULL, LOAD_LIBRARY_AS_DATAFILE);
/* Validate that this is really a theme */
if(!hTheme) goto invalid_theme;
if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szPackThemVersionResource))) {
TRACE("No version resource found\n");
goto invalid_theme;
}
if((versize = SizeofResource(hTheme, hrsc)) != 2)
{
TRACE("Version resource found, but wrong size: %ld\n", versize);
goto invalid_theme;
}
version = *(WORD*)LoadResource(hTheme, hrsc);
if(version != MSSTYLES_VERSION)
{
TRACE("Version of theme file is unsupported: 0x%04x\n", version);
goto invalid_theme;
}
if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szColorNamesResource))) {
TRACE("Color names resource not found\n");
goto invalid_theme;
}
pszColors = (LPWSTR)LoadResource(hTheme, hrsc);
if(!(hrsc = FindResourceW(hTheme, MAKEINTRESOURCEW(1), szSizeNamesResource))) {
TRACE("Size names resource not found\n");
goto invalid_theme;
}
pszSizes = (LPWSTR)LoadResource(hTheme, hrsc);
/* Validate requested color against whats available from the theme */
if(pszColorName) {
tmp = pszColors;
while(*tmp) {
if(!lstrcmpiW(pszColorName, tmp)) {
pszSelectedColor = tmp;
break;
}
tmp += lstrlenW(tmp)+1;
}
}
else
pszSelectedColor = pszColors; /* Use the default color */
/* Validate requested size against whats available from the theme */
if(pszSizeName) {
tmp = pszSizes;
while(*tmp) {
if(!lstrcmpiW(pszSizeName, tmp)) {
pszSelectedSize = tmp;
break;
}
tmp += lstrlenW(tmp)+1;
}
}
else
pszSelectedSize = pszSizes; /* Use the default size */
if(!pszSelectedColor || !pszSelectedSize) {
TRACE("Requested color/size (%s/%s) not found in theme\n",
debugstr_w(pszColorName), debugstr_w(pszSizeName));
hr = E_PROP_ID_UNSUPPORTED;
goto invalid_theme;
}
*tf = HeapAlloc(GetProcessHeap(), 0, sizeof(THEME_FILE));
(*tf)->hTheme = hTheme;
(*tf)->pszAvailColors = pszColors;
(*tf)->pszAvailSizes = pszSizes;
(*tf)->pszSelectedColor = pszSelectedColor;
(*tf)->pszSelectedSize = pszSelectedSize;
return S_OK;
invalid_theme:
if(hTheme) FreeLibrary(hTheme);
if(!hr) hr = HRESULT_FROM_WIN32(GetLastError());
return hr;
}
/***********************************************************************
* MSSTYLES_CloseThemeFile
*
* Close theme file and free resources
*/
void MSSTYLES_CloseThemeFile(PTHEME_FILE tf)
{
if(tf) {
if(tf->hTheme) FreeLibrary(tf->hTheme);
HeapFree(GetProcessHeap(), 0, tf);
}
}

37
dlls/uxtheme/msstyles.h Normal file
View File

@ -0,0 +1,37 @@
/*
* Internal msstyles related defines & declarations
*
* Copyright (C) 2003 Kevin Koltzau
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
#ifndef __WINE_MSSTYLES_H
#define __WINE_MSSTYLES_H
typedef struct _THEME_FILE {
HMODULE hTheme;
LPWSTR pszAvailColors;
LPWSTR pszAvailSizes;
LPWSTR pszSelectedColor;
LPWSTR pszSelectedSize;
} THEME_FILE, *PTHEME_FILE;
HRESULT MSSTYLES_OpenThemeFile(LPCWSTR lpThemeFile, LPCWSTR pszColorName, LPCWSTR pszSizeName, PTHEME_FILE *tf);
void MSSTYLES_CloseThemeFile(PTHEME_FILE tf);
#endif

View File

@ -26,9 +26,12 @@
#include "winbase.h" #include "winbase.h"
#include "winuser.h" #include "winuser.h"
#include "wingdi.h" #include "wingdi.h"
#include "winreg.h"
#include "shlwapi.h"
#include "uxtheme.h" #include "uxtheme.h"
#include "uxthemedll.h" #include "uxthemedll.h"
#include "msstyles.h"
#include "wine/debug.h" #include "wine/debug.h"
@ -38,11 +41,28 @@ WINE_DEFAULT_DEBUG_CHANNEL(uxtheme);
* Defines and global variables * Defines and global variables
*/ */
static const WCHAR szThemeManager[] = {
'S','o','f','t','w','a','r','e','\\',
'M','i','c','r','o','s','o','f','t','\\',
'W','i','n','d','o','w','s','\\',
'C','u','r','r','e','n','t','V','e','r','s','i','o','n','\\',
'T','h','e','m','e','M','a','n','a','g','e','r','\0'
};
static const WCHAR szThemeActive[] = {'T','h','e','m','e','A','c','t','i','v','e','\0'};
static const WCHAR szSizeName[] = {'S','i','z','e','N','a','m','e','\0'};
static const WCHAR szColorName[] = {'C','o','l','o','r','N','a','m','e','\0'};
static const WCHAR szDllName[] = {'D','l','l','N','a','m','e','\0'};
DWORD dwThemeAppProperties = STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS; DWORD dwThemeAppProperties = STAP_ALLOW_NONCLIENT | STAP_ALLOW_CONTROLS;
ATOM atWindowTheme; ATOM atWindowTheme;
ATOM atSubAppName; ATOM atSubAppName;
ATOM atSubIdList; ATOM atSubIdList;
BOOL bThemeActive = FALSE;
WCHAR szCurrentTheme[MAX_PATH];
WCHAR szCurrentColor[64];
WCHAR szCurrentSize[64];
/***********************************************************************/ /***********************************************************************/
/*********************************************************************** /***********************************************************************
@ -59,10 +79,65 @@ void UXTHEME_InitSystem()
const WCHAR szSubIdList[] = { const WCHAR szSubIdList[] = {
'u','x','_','s','u','b','i','d','l','s','t','\0' 'u','x','_','s','u','b','i','d','l','s','t','\0'
}; };
HKEY hKey;
LONG buffsize;
HRESULT hr;
WCHAR tmp[10];
PTHEME_FILE pt;
atWindowTheme = GlobalAddAtomW(szWindowTheme); atWindowTheme = GlobalAddAtomW(szWindowTheme);
atSubAppName = GlobalAddAtomW(szSubAppName); atSubAppName = GlobalAddAtomW(szSubAppName);
atSubIdList = GlobalAddAtomW(szSubIdList); atSubIdList = GlobalAddAtomW(szSubIdList);
/* Get current theme configuration */
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
TRACE("Loading theme config\n");
buffsize = sizeof(tmp)/sizeof(tmp[0]);
if(!RegQueryValueExW(hKey, szThemeActive, NULL, NULL, (LPBYTE)tmp, &buffsize)) {
bThemeActive = (tmp[0] != '0');
}
else {
bThemeActive = FALSE;
TRACE("Failed to get ThemeActive: %ld\n", GetLastError());
}
buffsize = sizeof(szCurrentColor)/sizeof(szCurrentColor[0]);
if(RegQueryValueExW(hKey, szColorName, NULL, NULL, (LPBYTE)szCurrentColor, &buffsize))
szCurrentColor[0] = '\0';
buffsize = sizeof(szCurrentSize)/sizeof(szCurrentSize[0]);
if(RegQueryValueExW(hKey, szSizeName, NULL, NULL, (LPBYTE)szCurrentSize, &buffsize))
szCurrentSize[0] = '\0';
if(SHRegGetPathW(hKey, NULL, szDllName, szCurrentTheme, 0))
szCurrentTheme[0] = '\0';
RegCloseKey(hKey);
}
else
TRACE("Failed to open theme registry key\n");
if(bThemeActive) {
/* Make sure the theme requested is actually valid */
hr = MSSTYLES_OpenThemeFile(szCurrentTheme,
szCurrentColor[0]?szCurrentColor:NULL,
szCurrentSize[0]?szCurrentSize:NULL,
&pt);
if(FAILED(hr)) {
bThemeActive = FALSE;
szCurrentTheme[0] = '\0';
szCurrentColor[0] = '\0';
szCurrentSize[0] = '\0';
}
else {
/* Make sure the global color & size match the theme */
lstrcpynW(szCurrentColor, pt->pszSelectedColor, sizeof(szCurrentColor)/sizeof(szCurrentColor[0]));
lstrcpynW(szCurrentSize, pt->pszSelectedSize, sizeof(szCurrentSize)/sizeof(szCurrentSize[0]));
MSSTYLES_CloseThemeFile(pt);
}
}
if(!bThemeActive)
TRACE("Themeing not active\n");
else
TRACE("Theme active: %s %s %s\n", debugstr_w(szCurrentTheme),
debugstr_w(szCurrentColor), debugstr_w(szCurrentSize));
} }
/*********************************************************************** /***********************************************************************
@ -70,8 +145,7 @@ void UXTHEME_InitSystem()
*/ */
BOOL WINAPI IsAppThemed(void) BOOL WINAPI IsAppThemed(void)
{ {
FIXME("stub\n"); return IsThemeActive();
return FALSE;
} }
/*********************************************************************** /***********************************************************************
@ -79,8 +153,8 @@ BOOL WINAPI IsAppThemed(void)
*/ */
BOOL WINAPI IsThemeActive(void) BOOL WINAPI IsThemeActive(void)
{ {
FIXME("stub\n"); TRACE("\n");
return FALSE; return bThemeActive;
} }
/*********************************************************************** /***********************************************************************
@ -91,8 +165,21 @@ BOOL WINAPI IsThemeActive(void)
*/ */
HRESULT WINAPI EnableTheming(BOOL fEnable) HRESULT WINAPI EnableTheming(BOOL fEnable)
{ {
FIXME("%d: stub\n", fEnable); HKEY hKey;
return ERROR_CALL_NOT_IMPLEMENTED; WCHAR szEnabled[] = {'0','\0'};
TRACE("(%d)\n", fEnable);
if(fEnable != bThemeActive) {
bThemeActive = fEnable;
if(bThemeActive) szEnabled[0] = '1';
if(!RegOpenKeyW(HKEY_CURRENT_USER, szThemeManager, &hKey)) {
RegSetValueExW(hKey, szThemeActive, 0, REG_SZ, (LPBYTE)szEnabled, sizeof(WCHAR));
RegCloseKey(hKey);
}
PostMessageW(HWND_BROADCAST, WM_THEMECHANGED, 0, 0);
}
return S_OK;
} }
/*********************************************************************** /***********************************************************************
@ -152,6 +239,8 @@ HRESULT WINAPI SetWindowTheme(HWND hwnd, LPCWSTR pszSubAppName,
hr = UXTHEME_SetWindowProperty(hwnd, atSubAppName, pszSubAppName); hr = UXTHEME_SetWindowProperty(hwnd, atSubAppName, pszSubAppName);
if(SUCCEEDED(hr)) if(SUCCEEDED(hr))
hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList); hr = UXTHEME_SetWindowProperty(hwnd, atSubIdList, pszSubIdList);
if(SUCCEEDED(hr))
PostMessageW(hwnd, WM_THEMECHANGED, 0, 0);
return hr; return hr;
} }
@ -162,8 +251,12 @@ HRESULT WINAPI GetCurrentThemeName(LPWSTR pszThemeFileName, int dwMaxNameChars,
LPWSTR pszColorBuff, int cchMaxColorChars, LPWSTR pszColorBuff, int cchMaxColorChars,
LPWSTR pszSizeBuff, int cchMaxSizeChars) LPWSTR pszSizeBuff, int cchMaxSizeChars)
{ {
FIXME("stub\n"); if(!bThemeActive)
return ERROR_CALL_NOT_IMPLEMENTED; return E_PROP_ID_UNSUPPORTED;
if(pszThemeFileName) lstrcpynW(pszThemeFileName, szCurrentTheme, dwMaxNameChars);
if(pszColorBuff) lstrcpynW(pszColorBuff, szCurrentColor, cchMaxColorChars);
if(pszSizeBuff) lstrcpynW(pszSizeBuff, szCurrentSize, cchMaxSizeChars);
return S_OK;
} }
/*********************************************************************** /***********************************************************************
@ -249,10 +342,10 @@ HRESULT WINAPI OpenThemeFile(LPCWSTR pszThemeFileName, LPCWSTR pszColorName,
LPCWSTR pszSizeName, HTHEMEFILE *hThemeFile, LPCWSTR pszSizeName, HTHEMEFILE *hThemeFile,
DWORD unknown) DWORD unknown)
{ {
FIXME("%s,%s,%s,%ld: stub\n", debugstr_w(pszThemeFileName), TRACE("(%s,%s,%s,%p,%ld)\n", debugstr_w(pszThemeFileName),
debugstr_w(pszColorName), debugstr_w(pszColorName), debugstr_w(pszSizeName),
debugstr_w(pszSizeName), unknown); hThemeFile, unknown);
return ERROR_CALL_NOT_IMPLEMENTED; return MSSTYLES_OpenThemeFile(pszThemeFileName, pszColorName, pszSizeName, (PTHEME_FILE*)hThemeFile);
} }
/********************************************************************** /**********************************************************************
@ -265,7 +358,8 @@ HRESULT WINAPI OpenThemeFile(LPCWSTR pszThemeFileName, LPCWSTR pszColorName,
*/ */
HRESULT WINAPI CloseThemeFile(HTHEMEFILE hThemeFile) HRESULT WINAPI CloseThemeFile(HTHEMEFILE hThemeFile)
{ {
FIXME("stub\n"); TRACE("(%p)\n", hThemeFile);
MSSTYLES_CloseThemeFile(hThemeFile);
return S_OK; return S_OK;
} }
@ -311,8 +405,20 @@ HRESULT WINAPI GetThemeDefaults(LPCWSTR pszThemeFileName, LPWSTR pszColorName,
DWORD dwColorNameLen, LPWSTR pszSizeName, DWORD dwColorNameLen, LPWSTR pszSizeName,
DWORD dwSizeNameLen) DWORD dwSizeNameLen)
{ {
FIXME("%s: stub\n", debugstr_w(pszThemeFileName)); PTHEME_FILE pt;
return ERROR_CALL_NOT_IMPLEMENTED; HRESULT hr;
TRACE("(%s,%p,%ld,%p,%ld)\n", debugstr_w(pszThemeFileName),
pszColorName, dwColorNameLen,
pszSizeName, dwSizeNameLen);
hr = MSSTYLES_OpenThemeFile(pszThemeFileName, NULL, NULL, &pt);
if(FAILED(hr)) return hr;
lstrcpynW(pszColorName, pt->pszSelectedColor, dwColorNameLen);
lstrcpynW(pszSizeName, pt->pszSelectedSize, dwSizeNameLen);
MSSTYLES_CloseThemeFile(pt);
return S_OK;
} }
/********************************************************************** /**********************************************************************
@ -354,13 +460,37 @@ HRESULT WINAPI EnumThemes(LPCWSTR pszThemePath, EnumThemeProc callback,
* NOTES * NOTES
* XP fails with E_POINTER when pszColorName points to a buffer smaller then 605 * XP fails with E_POINTER when pszColorName points to a buffer smaller then 605
* characters * characters
*
* Not very efficient that I'm opening & validating the theme every call, but
* this is undocumented and almost never called..
* (and this is how windows works too)
*/ */
HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName, HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
DWORD dwColorNum, LPWSTR pszColorName) DWORD dwColorNum, LPWSTR pszColorName)
{ {
FIXME("%s %s %ld: stub\n", debugstr_w(pszThemeFileName), PTHEME_FILE pt;
HRESULT hr;
LPWSTR tmp;
TRACE("(%s,%s,%ld)\n", debugstr_w(pszThemeFileName),
debugstr_w(pszSizeName), dwColorNum); debugstr_w(pszSizeName), dwColorNum);
return ERROR_CALL_NOT_IMPLEMENTED;
hr = MSSTYLES_OpenThemeFile(pszThemeFileName, NULL, pszSizeName, &pt);
if(FAILED(hr)) return hr;
tmp = pt->pszAvailColors;
while(dwColorNum && *tmp) {
dwColorNum--;
tmp += lstrlenW(tmp)+1;
}
if(!dwColorNum && *tmp) {
TRACE("%s\n", debugstr_w(tmp));
lstrcpyW(pszColorName, tmp);
}
else
hr = E_PROP_ID_UNSUPPORTED;
MSSTYLES_CloseThemeFile(pt);
return hr;
} }
/********************************************************************** /**********************************************************************
@ -383,12 +513,37 @@ HRESULT WINAPI EnumThemeColors(LPWSTR pszThemeFileName, LPWSTR pszSizeName,
* NOTES * NOTES
* XP fails with E_POINTER when pszSizeName points to a buffer smaller then 605 * XP fails with E_POINTER when pszSizeName points to a buffer smaller then 605
* characters * characters
*
* Not very efficient that I'm opening & validating the theme every call, but
* this is undocumented and almost never called..
* (and this is how windows works too)
*/ */
HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName, HRESULT WINAPI EnumThemeSizes(LPWSTR pszThemeFileName, LPWSTR pszColorName,
DWORD dwSizeNum, LPWSTR pszSizeName) DWORD dwSizeNum, LPWSTR pszSizeName)
{ {
FIXME("%s %s %ld: stub\n", debugstr_w(pszThemeFileName), debugstr_w(pszColorName), dwSizeNum); PTHEME_FILE pt;
return ERROR_CALL_NOT_IMPLEMENTED; HRESULT hr;
LPWSTR tmp;
TRACE("(%s,%s,%ld)\n", debugstr_w(pszThemeFileName),
debugstr_w(pszColorName), dwSizeNum);
hr = MSSTYLES_OpenThemeFile(pszThemeFileName, pszColorName, NULL, &pt);
if(FAILED(hr)) return hr;
tmp = pt->pszAvailSizes;
while(dwSizeNum && *tmp) {
dwSizeNum--;
tmp += lstrlenW(tmp)+1;
}
if(!dwSizeNum && *tmp) {
TRACE("%s\n", debugstr_w(tmp));
lstrcpyW(pszSizeName, tmp);
}
else
hr = E_PROP_ID_UNSUPPORTED;
MSSTYLES_CloseThemeFile(pt);
return hr;
} }
/********************************************************************** /**********************************************************************