aboutsummaryrefslogtreecommitdiff
path: root/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/libs/dutil/WixToolset.DUtil/thmutil.cpp')
-rw-r--r--src/libs/dutil/WixToolset.DUtil/thmutil.cpp993
1 files changed, 562 insertions, 431 deletions
diff --git a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
index 599021bf..1e7fa01a 100644
--- a/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
+++ b/src/libs/dutil/WixToolset.DUtil/thmutil.cpp
@@ -20,6 +20,7 @@
20#define ThmExitOnRequiredXmlQueryFailure(x, s, ...) ExitOnRequiredXmlQueryFailureSource(DUTIL_SOURCE_THMUTIL, x, s, __VA_ARGS__) 20#define ThmExitOnRequiredXmlQueryFailure(x, s, ...) ExitOnRequiredXmlQueryFailureSource(DUTIL_SOURCE_THMUTIL, x, s, __VA_ARGS__)
21#define ThmExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_THMUTIL, g, x, s, __VA_ARGS__) 21#define ThmExitOnGdipFailure(g, x, s, ...) ExitOnGdipFailureSource(DUTIL_SOURCE_THMUTIL, g, x, s, __VA_ARGS__)
22 22
23#define ThmExitOnUnexpectedAttribute(x, n, e, a) { x = ParseUnexpectedAttribute(n, e, a); if (FAILED(x)) { ExitFunction(); } }
23 24
24// from CommCtrl.h 25// from CommCtrl.h
25#ifndef BS_COMMANDLINK 26#ifndef BS_COMMANDLINK
@@ -86,17 +87,33 @@ static HRESULT ParseTheme(
86 __in IXMLDOMDocument* pixd, 87 __in IXMLDOMDocument* pixd,
87 __out THEME** ppTheme 88 __out THEME** ppTheme
88 ); 89 );
89static HRESULT ParseImage( 90static HRESULT GetAttributeImageFileOrResource(
90 __in_opt HMODULE hModule, 91 __in_opt HMODULE hModule,
91 __in_z_opt LPCWSTR wzRelativePath, 92 __in_z_opt LPCWSTR wzRelativePath,
92 __in IXMLDOMNode* pElement, 93 __in IXMLDOMNode* pElement,
93 __out HBITMAP* phImage 94 __out HBITMAP* phImage
94 ); 95 );
95static HRESULT ParseIcon( 96static HRESULT ParseCommandLinkImage(
96 __in_opt HMODULE hModule, 97 __in_opt HMODULE hModule,
97 __in_z_opt LPCWSTR wzRelativePath, 98 __in_z_opt LPCWSTR wzRelativePath,
98 __in IXMLDOMNode* pElement, 99 __in IXMLDOMNode* pElement,
99 __out HICON* phIcon 100 __in THEME_CONTROL* pControl
101 );
102static HRESULT GetAttributeCoordinateOrDimension(
103 __in IXMLDOMNode* pixn,
104 __in LPCWSTR wzAttribute,
105 __inout int* pnValue
106 );
107static HRESULT GetAttributeFontId(
108 __in IXMLDOMNode* pixn,
109 __in LPCWSTR wzAttribute,
110 __inout DWORD* pdwValue
111 );
112static HRESULT ParseSourceXY(
113 __in IXMLDOMNode* pixn,
114 __in BOOL fAllowed,
115 __inout int* pnX,
116 __inout int* pnY
100 ); 117 );
101static HRESULT ParseWindow( 118static HRESULT ParseWindow(
102 __in_opt HMODULE hModule, 119 __in_opt HMODULE hModule,
@@ -138,6 +155,7 @@ static HRESULT ParseControl(
138 __in_opt HMODULE hModule, 155 __in_opt HMODULE hModule,
139 __in_opt LPCWSTR wzRelativePath, 156 __in_opt LPCWSTR wzRelativePath,
140 __in IXMLDOMNode* pixn, 157 __in IXMLDOMNode* pixn,
158 __in_z LPCWSTR wzElementName,
141 __in THEME* pTheme, 159 __in THEME* pTheme,
142 __in THEME_CONTROL* pControl, 160 __in THEME_CONTROL* pControl,
143 __in_opt THEME_PAGE* pPage 161 __in_opt THEME_PAGE* pPage
@@ -183,6 +201,11 @@ static HRESULT ParseTooltips(
183 __in THEME_CONTROL* pControl, 201 __in THEME_CONTROL* pControl,
184 __inout BOOL* pfAnyChildren 202 __inout BOOL* pfAnyChildren
185 ); 203 );
204static HRESULT ParseUnexpectedAttribute(
205 __in IXMLDOMNode* pixn,
206 __in_z LPCWSTR wzElementName,
207 __in_z LPCWSTR wzAttribute
208 );
186static HRESULT ParseNotes( 209static HRESULT ParseNotes(
187 __in IXMLDOMNode* pixn, 210 __in IXMLDOMNode* pixn,
188 __in THEME_CONTROL* pControl, 211 __in THEME_CONTROL* pControl,
@@ -1698,6 +1721,7 @@ static HRESULT ParseTheme(
1698 HRESULT hr = S_OK; 1721 HRESULT hr = S_OK;
1699 THEME* pTheme = NULL; 1722 THEME* pTheme = NULL;
1700 IXMLDOMElement *pThemeElement = NULL; 1723 IXMLDOMElement *pThemeElement = NULL;
1724 BOOL fXmlFound = FALSE;
1701 1725
1702 hr = pixd->get_documentElement(&pThemeElement); 1726 hr = pixd->get_documentElement(&pThemeElement);
1703 ThmExitOnFailure(hr, "Failed to get theme element."); 1727 ThmExitOnFailure(hr, "Failed to get theme element.");
@@ -1709,8 +1733,8 @@ static HRESULT ParseTheme(
1709 pTheme->nDpi = USER_DEFAULT_SCREEN_DPI; 1733 pTheme->nDpi = USER_DEFAULT_SCREEN_DPI;
1710 1734
1711 // Parse the optional background resource image. 1735 // Parse the optional background resource image.
1712 hr = ParseImage(hModule, wzRelativePath, pThemeElement, &pTheme->hImage); 1736 hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pThemeElement, &pTheme->hImage);
1713 ThmExitOnFailure(hr, "Failed while parsing theme image."); 1737 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed while parsing theme image.");
1714 1738
1715 // Parse the fonts. 1739 // Parse the fonts.
1716 hr = ParseFonts(pThemeElement, pTheme); 1740 hr = ParseFonts(pThemeElement, pTheme);
@@ -1734,7 +1758,7 @@ LExit:
1734 return hr; 1758 return hr;
1735} 1759}
1736 1760
1737static HRESULT ParseImage( 1761static HRESULT GetAttributeImageFileOrResource(
1738 __in_opt HMODULE hModule, 1762 __in_opt HMODULE hModule,
1739 __in_z_opt LPCWSTR wzRelativePath, 1763 __in_z_opt LPCWSTR wzRelativePath,
1740 __in IXMLDOMNode* pElement, 1764 __in IXMLDOMNode* pElement,
@@ -1744,45 +1768,44 @@ static HRESULT ParseImage(
1744 HRESULT hr = S_OK; 1768 HRESULT hr = S_OK;
1745 BSTR bstr = NULL; 1769 BSTR bstr = NULL;
1746 LPWSTR sczImageFile = NULL; 1770 LPWSTR sczImageFile = NULL;
1747 int iResourceId = 0; 1771 WORD wResourceId = 0;
1772 BOOL fFound = FALSE;
1748 Gdiplus::Bitmap* pBitmap = NULL; 1773 Gdiplus::Bitmap* pBitmap = NULL;
1749 *phImage = NULL; 1774 *phImage = NULL;
1750 1775
1751 hr = XmlGetAttribute(pElement, L"ImageResource", &bstr); 1776 hr = XmlGetAttributeUInt16(pElement, L"ImageResource", &wResourceId);
1752 ThmExitOnFailure(hr, "Failed to get image resource attribute."); 1777 ThmExitOnOptionalXmlQueryFailure(hr, fFound, "Failed to get image resource attribute.");
1753 1778
1754 if (S_OK == hr) 1779 if (fFound)
1755 { 1780 {
1756 iResourceId = wcstol(bstr, NULL, 10); 1781 hr = GdipBitmapFromResource(hModule, MAKEINTRESOURCE(wResourceId), &pBitmap);
1757 1782 ThmExitOnFailure(hr, "Failed to load image from resource: %hu", wResourceId);
1758 hr = GdipBitmapFromResource(hModule, MAKEINTRESOURCE(iResourceId), &pBitmap);
1759 // Don't fail.
1760 } 1783 }
1761 1784
1762 ReleaseNullBSTR(bstr); 1785 hr = XmlGetAttribute(pElement, L"ImageFile", &bstr);
1786 ThmExitOnOptionalXmlQueryFailure(hr, fFound, "Failed to get image file attribute.");
1763 1787
1764 // Parse the optional background image from a given file. 1788 if (fFound)
1765 if (!pBitmap)
1766 { 1789 {
1767 hr = XmlGetAttribute(pElement, L"ImageFile", &bstr); 1790 if (pBitmap)
1768 ThmExitOnFailure(hr, "Failed to get image file attribute.");
1769
1770 if (S_OK == hr)
1771 { 1791 {
1772 if (wzRelativePath) 1792 ThmExitWithRootFailure(hr, E_INVALIDDATA, "ImageFile attribute can't be specified with ImageResource attribute.");
1773 { 1793 }
1774 hr = PathConcat(wzRelativePath, bstr, &sczImageFile);
1775 ThmExitOnFailure(hr, "Failed to combine image file path.");
1776 }
1777 else
1778 {
1779 hr = PathRelativeToModule(&sczImageFile, bstr, hModule);
1780 ThmExitOnFailure(hr, "Failed to get image filename.");
1781 }
1782 1794
1783 hr = GdipBitmapFromFile(sczImageFile, &pBitmap); 1795 // Parse the optional background image from a given file.
1784 // Don't fail. 1796 if (wzRelativePath)
1797 {
1798 hr = PathConcat(wzRelativePath, bstr, &sczImageFile);
1799 ThmExitOnFailure(hr, "Failed to combine image file path.");
1800 }
1801 else
1802 {
1803 hr = PathRelativeToModule(&sczImageFile, bstr, hModule);
1804 ThmExitOnFailure(hr, "Failed to get image filename.");
1785 } 1805 }
1806
1807 hr = GdipBitmapFromFile(sczImageFile, &pBitmap);
1808 ThmExitOnFailure(hr, "Failed to load image from file: %ls", sczImageFile);
1786 } 1809 }
1787 1810
1788 // If there is an image, convert it into a bitmap handle. 1811 // If there is an image, convert it into a bitmap handle.
@@ -1792,8 +1815,10 @@ static HRESULT ParseImage(
1792 Gdiplus::Status gs = pBitmap->GetHBITMAP(black, phImage); 1815 Gdiplus::Status gs = pBitmap->GetHBITMAP(black, phImage);
1793 ThmExitOnGdipFailure(gs, hr, "Failed to convert GDI+ bitmap into HBITMAP."); 1816 ThmExitOnGdipFailure(gs, hr, "Failed to convert GDI+ bitmap into HBITMAP.");
1794 } 1817 }
1795 1818 else
1796 hr = S_OK; 1819 {
1820 hr = E_NOTFOUND;
1821 }
1797 1822
1798LExit: 1823LExit:
1799 if (pBitmap) 1824 if (pBitmap)
@@ -1808,62 +1833,244 @@ LExit:
1808} 1833}
1809 1834
1810 1835
1811static HRESULT ParseIcon( 1836static HRESULT ParseOwnerDrawImage(
1812 __in_opt HMODULE hModule, 1837 __in_opt HMODULE hModule,
1813 __in_z_opt LPCWSTR wzRelativePath, 1838 __in_z_opt LPCWSTR wzRelativePath,
1839 __in THEME* pTheme,
1814 __in IXMLDOMNode* pElement, 1840 __in IXMLDOMNode* pElement,
1815 __out HICON* phIcon 1841 __in THEME_CONTROL* pControl
1816 ) 1842 )
1817{ 1843{
1818 HRESULT hr = S_OK; 1844 HRESULT hr = S_OK;
1819 BSTR bstr = NULL; 1845 BOOL fXmlFound = FALSE;
1820 LPWSTR sczImageFile = NULL; 1846 BOOL fFoundImage = FALSE;
1821 int iResourceId = 0;
1822 *phIcon = NULL;
1823 1847
1824 hr = XmlGetAttribute(pElement, L"IconResource", &bstr); 1848 // Parse the optional background resource image.
1825 ThmExitOnFailure(hr, "Failed to get icon resource attribute."); 1849 hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pElement, &pControl->hImage);
1850 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed while parsing control image.");
1826 1851
1827 if (S_OK == hr) 1852 if (fXmlFound)
1853 {
1854 fFoundImage = TRUE;
1855 }
1856
1857 hr = ParseSourceXY(pElement, NULL != pTheme->hImage, &pControl->nSourceX, &pControl->nSourceY);
1858 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get control SourceX and SourceY attributes.");
1859
1860 if (fXmlFound)
1828 { 1861 {
1829 iResourceId = wcstol(bstr, NULL, 10); 1862 if (fFoundImage)
1863 {
1864 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected SourceX attribute with image attribute.");
1865 }
1866 else if (1 > pControl->nWidth || 1 > pControl->nHeight)
1867 {
1868 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Control Width and Height must be positive when using SourceX and SourceY.");
1869 }
1830 1870
1831 *phIcon = reinterpret_cast<HICON>(::LoadImageW(hModule, MAKEINTRESOURCEW(iResourceId), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE)); 1871 fFoundImage = TRUE;
1832 ThmExitOnNullWithLastError(*phIcon, hr, "Failed to load icon.");
1833 } 1872 }
1834 else 1873
1874 if (THEME_CONTROL_TYPE_IMAGE == pControl->type && !fFoundImage)
1835 { 1875 {
1836 ReleaseNullBSTR(bstr); 1876 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Image control didn't specify an image.");
1877 }
1837 1878
1838 hr = XmlGetAttribute(pElement, L"IconFile", &bstr); 1879LExit:
1839 ThmExitOnFailure(hr, "Failed to get icon file attribute."); 1880 return hr;
1881}
1840 1882
1841 if (S_OK == hr) 1883
1884static HRESULT ParseCommandLinkImage(
1885 __in_opt HMODULE hModule,
1886 __in_z_opt LPCWSTR wzRelativePath,
1887 __in IXMLDOMNode* pElement,
1888 __in THEME_CONTROL* pControl
1889 )
1890{
1891 HRESULT hr = S_OK;
1892 BSTR bstr = NULL;
1893 BOOL fImageFound = FALSE;
1894 BOOL fXmlFound = FALSE;
1895 LPWSTR sczIconFile = NULL;
1896 WORD wResourceId = 0;
1897
1898 hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pElement, &pControl->hImage);
1899 ThmExitOnOptionalXmlQueryFailure(hr, fImageFound, "Failed to parse image attributes for CommandLink.");
1900
1901 hr = XmlGetAttributeUInt16(pElement, L"IconResource", &wResourceId);
1902 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get icon resource attribute.");
1903
1904 if (fXmlFound)
1905 {
1906 if (fImageFound)
1842 { 1907 {
1843 if (wzRelativePath) 1908 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected IconResource attribute with image attribute.");
1844 { 1909 }
1845 hr = PathConcat(wzRelativePath, bstr, &sczImageFile); 1910
1846 ThmExitOnFailure(hr, "Failed to combine image file path."); 1911 pControl->hIcon = reinterpret_cast<HICON>(::LoadImageW(hModule, MAKEINTRESOURCEW(wResourceId), IMAGE_ICON, 0, 0, LR_DEFAULTSIZE));
1847 } 1912 ThmExitOnNullWithLastError(pControl->hIcon, hr, "Failed to load icon.");
1848 else 1913 }
1849 { 1914
1850 hr = PathRelativeToModule(&sczImageFile, bstr, hModule); 1915 hr = XmlGetAttribute(pElement, L"IconFile", &bstr);
1851 ThmExitOnFailure(hr, "Failed to get image filename."); 1916 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get icon file attribute.");
1852 } 1917
1918 if (fXmlFound)
1919 {
1920 if (fImageFound)
1921 {
1922 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Unexpected IconFile attribute with image attribute.");
1923 }
1924 else if (pControl->hIcon)
1925 {
1926 ThmExitWithRootFailure(hr, E_INVALIDDATA, "IconFile attribute can't be specified with IconResource attribute.");
1927 }
1853 1928
1854 *phIcon = reinterpret_cast<HICON>(::LoadImageW(NULL, sczImageFile, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE)); 1929 if (wzRelativePath)
1855 ThmExitOnNullWithLastError(*phIcon, hr, "Failed to load icon: %ls.", sczImageFile); 1930 {
1931 hr = PathConcat(wzRelativePath, bstr, &sczIconFile);
1932 ThmExitOnFailure(hr, "Failed to combine image file path.");
1856 } 1933 }
1934 else
1935 {
1936 hr = PathRelativeToModule(&sczIconFile, bstr, hModule);
1937 ThmExitOnFailure(hr, "Failed to get image filename.");
1938 }
1939
1940 pControl->hIcon = reinterpret_cast<HICON>(::LoadImageW(NULL, sczIconFile, IMAGE_ICON, 0, 0, LR_DEFAULTSIZE | LR_LOADFROMFILE));
1941 ThmExitOnNullWithLastError(pControl->hIcon, hr, "Failed to load icon: %ls.", sczIconFile);
1857 } 1942 }
1858 1943
1944 ThmExitOnUnexpectedAttribute(hr, pElement, L"CommandLink", L"SourceX");
1945 ThmExitOnUnexpectedAttribute(hr, pElement, L"CommandLink", L"SourceY");
1946
1859LExit: 1947LExit:
1860 ReleaseStr(sczImageFile); 1948 ReleaseStr(sczIconFile);
1861 ReleaseBSTR(bstr); 1949 ReleaseBSTR(bstr);
1862 1950
1863 return hr; 1951 return hr;
1864} 1952}
1865 1953
1866 1954
1955static HRESULT GetAttributeCoordinateOrDimension(
1956 __in IXMLDOMNode* pixn,
1957 __in LPCWSTR wzAttribute,
1958 __inout int* pnValue
1959 )
1960{
1961 HRESULT hr = S_OK;
1962 int nValue = 0;
1963 BOOL fXmlFound = FALSE;
1964
1965 hr = XmlGetAttributeInt32(pixn, wzAttribute, &nValue);
1966 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get coordinate or dimension attribute.");
1967
1968 if (!fXmlFound)
1969 {
1970 ExitFunction1(hr = E_NOTFOUND);
1971 }
1972 else if (abs(nValue) > SHORT_MAX)
1973 {
1974 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Invalid coordinate or dimension attribute value: %i", nValue);
1975 }
1976
1977 *pnValue = nValue;
1978
1979LExit:
1980 return hr;
1981}
1982
1983static HRESULT GetAttributeFontId(
1984 __in IXMLDOMNode* pixn,
1985 __in LPCWSTR wzAttribute,
1986 __inout DWORD* pdwValue
1987 )
1988{
1989 HRESULT hr = S_OK;
1990 DWORD dwValue = 0;
1991 BOOL fXmlFound = FALSE;
1992
1993 hr = XmlGetAttributeUInt32(pixn, wzAttribute, &dwValue);
1994 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get font id attribute.");
1995
1996 if (!fXmlFound)
1997 {
1998 ExitFunction1(hr = E_NOTFOUND);
1999 }
2000 else if (THEME_INVALID_ID == dwValue)
2001 {
2002 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Invalid font id value: %u", dwValue);
2003 }
2004
2005 *pdwValue = dwValue;
2006
2007LExit:
2008 return hr;
2009}
2010
2011static HRESULT ParseSourceXY(
2012 __in IXMLDOMNode* pixn,
2013 __in BOOL fAllowed,
2014 __inout int* pnX,
2015 __inout int* pnY
2016 )
2017{
2018 HRESULT hr = S_OK;
2019 BOOL fXFound = FALSE;
2020 BOOL fYFound = FALSE;
2021
2022 hr = GetAttributeCoordinateOrDimension(pixn, L"SourceX", pnX);
2023 ThmExitOnOptionalXmlQueryFailure(hr, fXFound, "Failed to get SourceX attribute.");
2024
2025 if (!fXFound)
2026 {
2027 *pnX = -1;
2028 }
2029 else
2030 {
2031 if (!fAllowed)
2032 {
2033 ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceX cannot be specified without an image specified on Theme.");
2034 }
2035 else if (0 > *pnX)
2036 {
2037 ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceX must be non-negative.");
2038 }
2039 }
2040
2041 hr = GetAttributeCoordinateOrDimension(pixn, L"SourceY", pnY);
2042 ThmExitOnOptionalXmlQueryFailure(hr, fYFound, "Failed to get SourceY attribute.");
2043
2044 if (!fYFound)
2045 {
2046 if (fXFound)
2047 {
2048 ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY must be specified with SourceX.");
2049 }
2050
2051 *pnY = -1;
2052 hr = E_NOTFOUND;
2053 }
2054 else
2055 {
2056 if (!fAllowed)
2057 {
2058 ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY cannot be specified without an image specified on Theme.");
2059 }
2060 else if (!fXFound)
2061 {
2062 ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY must be specified with SourceX.");
2063 }
2064 else if (0 > *pnY)
2065 {
2066 ThmExitWithRootFailure(hr, E_INVALIDDATA, "SourceY must be non-negative.");
2067 }
2068 }
2069
2070LExit:
2071 return hr;
2072}
2073
1867static HRESULT ParseWindow( 2074static HRESULT ParseWindow(
1868 __in_opt HMODULE hModule, 2075 __in_opt HMODULE hModule,
1869 __in_opt LPCWSTR wzRelativePath, 2076 __in_opt LPCWSTR wzRelativePath,
@@ -1873,77 +2080,79 @@ static HRESULT ParseWindow(
1873{ 2080{
1874 HRESULT hr = S_OK; 2081 HRESULT hr = S_OK;
1875 IXMLDOMNode* pixn = NULL; 2082 IXMLDOMNode* pixn = NULL;
1876 DWORD dwValue = 0; 2083 BOOL fXmlFound = FALSE;
2084 int nValue = 0;
1877 BSTR bstr = NULL; 2085 BSTR bstr = NULL;
1878 LPWSTR sczIconFile = NULL; 2086 LPWSTR sczIconFile = NULL;
1879 2087
1880 hr = XmlSelectSingleNode(pElement, L"Window", &pixn); 2088 hr = XmlSelectSingleNode(pElement, L"Window", &pixn);
1881 if (S_FALSE == hr) 2089 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find window element.");
1882 {
1883 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
1884 }
1885 ThmExitOnFailure(hr, "Failed to find window element.");
1886 2090
1887 hr = XmlGetYesNoAttribute(pixn, L"AutoResize", &pTheme->fAutoResize); 2091 hr = XmlGetYesNoAttribute(pixn, L"AutoResize", &pTheme->fAutoResize);
1888 if (E_NOTFOUND == hr) 2092 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window AutoResize attribute.");
1889 {
1890 hr = S_OK;
1891 }
1892 ThmExitOnFailure(hr, "Failed to get window AutoResize attribute.");
1893
1894 hr = XmlGetAttributeNumber(pixn, L"Width", &dwValue);
1895 if (S_FALSE == hr)
1896 {
1897 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
1898 ThmExitOnRootFailure(hr, "Failed to find window Width attribute.");
1899 }
1900 ThmExitOnFailure(hr, "Failed to get window Width attribute.");
1901 2093
1902 pTheme->nWidth = pTheme->nDefaultDpiWidth = pTheme->nWindowWidth = dwValue; 2094 hr = GetAttributeCoordinateOrDimension(pixn, L"Width", &nValue);
2095 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to get window Width attribute.");
1903 2096
1904 hr = XmlGetAttributeNumber(pixn, L"Height", &dwValue); 2097 if (1 > nValue)
1905 if (S_FALSE == hr)
1906 { 2098 {
1907 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); 2099 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Window/@Width must be positive: %i", nValue);
1908 ThmExitOnRootFailure(hr, "Failed to find window Height attribute.");
1909 } 2100 }
1910 ThmExitOnFailure(hr, "Failed to get window Height attribute.");
1911 2101
1912 pTheme->nHeight = pTheme->nDefaultDpiHeight = pTheme->nWindowHeight = dwValue; 2102 pTheme->nWidth = pTheme->nDefaultDpiWidth = pTheme->nWindowWidth = nValue;
1913 2103
1914 hr = XmlGetAttributeNumber(pixn, L"MinimumWidth", &dwValue); 2104 hr = GetAttributeCoordinateOrDimension(pixn, L"Height", &nValue);
1915 if (S_FALSE == hr) 2105 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to get window Height attribute.");
2106
2107 if (1 > nValue)
1916 { 2108 {
1917 dwValue = 0; 2109 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Window/@Height must be positive: %i", nValue);
1918 hr = S_OK;
1919 } 2110 }
1920 ThmExitOnFailure(hr, "Failed to get window MinimumWidth attribute.");
1921 2111
1922 pTheme->nMinimumWidth = pTheme->nDefaultDpiMinimumWidth = dwValue; 2112 pTheme->nHeight = pTheme->nDefaultDpiHeight = pTheme->nWindowHeight = nValue;
1923 2113
1924 hr = XmlGetAttributeNumber(pixn, L"MinimumHeight", &dwValue); 2114 hr = GetAttributeCoordinateOrDimension(pixn, L"MinimumWidth", &nValue);
1925 if (S_FALSE == hr) 2115 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window MinimumWidth attribute.");
2116
2117 if (fXmlFound)
1926 { 2118 {
1927 dwValue = 0; 2119 if (!pTheme->fAutoResize)
1928 hr = S_OK; 2120 {
2121 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Window/@MinimumWidth can't be specified unless AutoResize is enabled.");
2122 }
2123 else if (1 > nValue || pTheme->nWidth < nValue)
2124 {
2125 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Window/@MinimumWidth must be positive and not greater than Window/@Width: %i", nValue);
2126 }
2127
2128 pTheme->nMinimumWidth = pTheme->nDefaultDpiMinimumWidth = nValue;
1929 } 2129 }
1930 ThmExitOnFailure(hr, "Failed to get window MinimumHeight attribute.");
1931 2130
1932 pTheme->nMinimumHeight = pTheme->nDefaultDpiMinimumHeight = dwValue; 2131 hr = GetAttributeCoordinateOrDimension(pixn, L"MinimumHeight", &nValue);
2132 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window MinimumHeight attribute.");
1933 2133
1934 hr = XmlGetAttributeNumber(pixn, L"FontId", &pTheme->dwFontId); 2134 if (fXmlFound)
1935 if (S_FALSE == hr)
1936 { 2135 {
1937 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); 2136 if (!pTheme->fAutoResize)
1938 ThmExitOnRootFailure(hr, "Failed to find window FontId attribute."); 2137 {
2138 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Window/@MinimumHeight can't be specified unless AutoResize is enabled.");
2139 }
2140 else if (1 > nValue || pTheme->nHeight < nValue)
2141 {
2142 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Window/@MinimumHeight must be positive and not greater than Window/@Height: %i", nValue);
2143 }
2144
2145 pTheme->nMinimumHeight = pTheme->nDefaultDpiMinimumHeight = nValue;
1939 } 2146 }
1940 ThmExitOnFailure(hr, "Failed to get window FontId attribute."); 2147
2148 hr = GetAttributeFontId(pixn, L"FontId", &pTheme->dwFontId);
2149 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to get window FontId attribute.");
1941 2150
1942 // Get the optional window icon from a resource. 2151 // Get the optional window icon from a resource.
1943 hr = XmlGetAttribute(pixn, L"IconResource", &bstr); 2152 hr = XmlGetAttribute(pixn, L"IconResource", &bstr);
1944 ThmExitOnFailure(hr, "Failed to get window IconResource attribute."); 2153 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window IconResource attribute.");
1945 2154
1946 if (S_OK == hr) 2155 if (fXmlFound)
1947 { 2156 {
1948 pTheme->hIcon = ::LoadIconW(hModule, bstr); 2157 pTheme->hIcon = ::LoadIconW(hModule, bstr);
1949 ThmExitOnNullWithLastError(pTheme->hIcon, hr, "Failed to load window icon from IconResource."); 2158 ThmExitOnNullWithLastError(pTheme->hIcon, hr, "Failed to load window icon from IconResource.");
@@ -1953,10 +2162,15 @@ static HRESULT ParseWindow(
1953 2162
1954 // Get the optional window icon from a file. 2163 // Get the optional window icon from a file.
1955 hr = XmlGetAttribute(pixn, L"IconFile", &bstr); 2164 hr = XmlGetAttribute(pixn, L"IconFile", &bstr);
1956 ThmExitOnFailure(hr, "Failed to get window IconFile attribute."); 2165 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window IconFile attribute.");
1957 2166
1958 if (S_OK == hr) 2167 if (fXmlFound)
1959 { 2168 {
2169 if (pTheme->hIcon)
2170 {
2171 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Window/@IconFile can't be specified with IconResource.");
2172 }
2173
1960 if (wzRelativePath) 2174 if (wzRelativePath)
1961 { 2175 {
1962 hr = PathConcat(wzRelativePath, bstr, &sczIconFile); 2176 hr = PathConcat(wzRelativePath, bstr, &sczIconFile);
@@ -1974,48 +2188,37 @@ static HRESULT ParseWindow(
1974 ReleaseNullBSTR(bstr); 2188 ReleaseNullBSTR(bstr);
1975 } 2189 }
1976 2190
1977 hr = XmlGetAttributeNumber(pixn, L"SourceX", reinterpret_cast<DWORD*>(&pTheme->nSourceX)); 2191 hr = ParseSourceXY(pixn, NULL != pTheme->hImage, &pTheme->nSourceX, &pTheme->nSourceY);
1978 if (S_FALSE == hr) 2192 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window SourceX and SourceY attributes.");
1979 {
1980 pTheme->nSourceX = -1;
1981 }
1982 ThmExitOnFailure(hr, "Failed to get window SourceX attribute.");
1983
1984 hr = XmlGetAttributeNumber(pixn, L"SourceY", reinterpret_cast<DWORD*>(&pTheme->nSourceY));
1985 if (S_FALSE == hr)
1986 {
1987 pTheme->nSourceY = -1;
1988 }
1989 ThmExitOnFailure(hr, "Failed to get window SourceY attribute.");
1990 2193
1991 // Parse the optional window style. 2194 // Parse the optional window style.
1992 hr = XmlGetAttributeNumberBase(pixn, L"HexStyle", 16, &pTheme->dwStyle); 2195 hr = XmlGetAttributeNumberBase(pixn, L"HexStyle", 16, &pTheme->dwStyle);
1993 ThmExitOnFailure(hr, "Failed to get theme window style (Window@HexStyle) attribute."); 2196 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get theme window style (Window@HexStyle) attribute.");
1994 2197
1995 if (S_FALSE == hr) 2198 if (!fXmlFound)
1996 { 2199 {
1997 pTheme->dwStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_SYSMENU; 2200 pTheme->dwStyle = WS_VISIBLE | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION;
1998 pTheme->dwStyle |= (0 <= pTheme->nSourceX && 0 <= pTheme->nSourceY) ? WS_POPUP : WS_OVERLAPPED; 2201 pTheme->dwStyle |= (0 <= pTheme->nSourceX && 0 <= pTheme->nSourceY) ? WS_POPUP : WS_OVERLAPPED;
1999 } 2202 }
2000 2203
2001 hr = XmlGetAttributeNumber(pixn, L"StringId", reinterpret_cast<DWORD*>(&pTheme->uStringId)); 2204 hr = XmlGetAttributeUInt32(pixn, L"StringId", reinterpret_cast<DWORD*>(&pTheme->uStringId));
2002 ThmExitOnFailure(hr, "Failed to get window StringId attribute."); 2205 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window StringId attribute.");
2003 2206
2004 if (S_FALSE == hr) 2207 if (!fXmlFound)
2005 { 2208 {
2006 pTheme->uStringId = UINT_MAX; 2209 pTheme->uStringId = UINT_MAX;
2210 }
2211 else if (UINT_MAX == pTheme->uStringId)
2212 {
2213 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Invalid StringId: %u", pTheme->uStringId);
2214 }
2007 2215
2008 hr = XmlGetAttribute(pixn, L"Caption", &bstr); 2216 hr = XmlGetAttributeEx(pixn, L"Caption", &pTheme->sczCaption);
2009 ThmExitOnFailure(hr, "Failed to get window Caption attribute."); 2217 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get window Caption attribute.");
2010
2011 if (S_FALSE == hr)
2012 {
2013 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2014 ThmExitOnRootFailure(hr, "Window elements must contain the Caption or StringId attribute.");
2015 }
2016 2218
2017 hr = StrAllocString(&pTheme->sczCaption, bstr, 0); 2219 if (fXmlFound && UINT_MAX != pTheme->uStringId || !fXmlFound && UINT_MAX == pTheme->uStringId)
2018 ThmExitOnFailure(hr, "Failed to copy window Caption attribute."); 2220 {
2221 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Window elements must contain either the Caption or StringId attribute.");
2019 } 2222 }
2020 2223
2021 // Parse any image lists. 2224 // Parse any image lists.
@@ -2049,6 +2252,7 @@ static HRESULT ParseFonts(
2049 IXMLDOMNode* pixn = NULL; 2252 IXMLDOMNode* pixn = NULL;
2050 BSTR bstrName = NULL; 2253 BSTR bstrName = NULL;
2051 DWORD dwId = 0; 2254 DWORD dwId = 0;
2255 BOOL fXmlFound = FALSE;
2052 COLORREF crForeground = THEME_INVISIBLE_COLORREF; 2256 COLORREF crForeground = THEME_INVISIBLE_COLORREF;
2053 COLORREF crBackground = THEME_INVISIBLE_COLORREF; 2257 COLORREF crBackground = THEME_INVISIBLE_COLORREF;
2054 DWORD dwSystemForegroundColor = FALSE; 2258 DWORD dwSystemForegroundColor = FALSE;
@@ -2062,7 +2266,7 @@ static HRESULT ParseFonts(
2062 2266
2063 if (!pTheme->cFonts) 2267 if (!pTheme->cFonts)
2064 { 2268 {
2065 ExitFunction1(hr = S_OK); 2269 ThmExitOnRootFailure(hr = E_INVALIDDATA, "No font elements found.");
2066 } 2270 }
2067 2271
2068 pTheme->rgFonts = static_cast<THEME_FONT*>(MemAlloc(sizeof(THEME_FONT) * pTheme->cFonts, TRUE)); 2272 pTheme->rgFonts = static_cast<THEME_FONT*>(MemAlloc(sizeof(THEME_FONT) * pTheme->cFonts, TRUE));
@@ -2070,66 +2274,52 @@ static HRESULT ParseFonts(
2070 2274
2071 while (S_OK == (hr = XmlNextElement(pixnl, &pixn, NULL))) 2275 while (S_OK == (hr = XmlNextElement(pixnl, &pixn, NULL)))
2072 { 2276 {
2073 hr = XmlGetAttributeNumber(pixn, L"Id", &dwId); 2277 hr = GetAttributeFontId(pixn, L"Id", &dwId);
2074 if (S_FALSE == hr) 2278 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find font id.");
2075 {
2076 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2077 }
2078 ThmExitOnFailure(hr, "Failed to find font id.");
2079 2279
2080 if (pTheme->cFonts <= dwId) 2280 if (pTheme->cFonts <= dwId)
2081 { 2281 {
2082 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); 2282 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Invalid theme font id: %u.", dwId);
2083 ThmExitOnRootFailure(hr, "Invalid theme font id.");
2084 } 2283 }
2085 2284
2086 THEME_FONT* pFont = pTheme->rgFonts + dwId; 2285 THEME_FONT* pFont = pTheme->rgFonts + dwId;
2087 if (pFont->cFontInstances) 2286 if (pFont->cFontInstances)
2088 { 2287 {
2089 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); 2288 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Theme font id duplicated.");
2090 ThmExitOnRootFailure(hr, "Theme font id duplicated.");
2091 } 2289 }
2092 2290
2093 pFont->lfQuality = CLEARTYPE_QUALITY; 2291 pFont->lfQuality = CLEARTYPE_QUALITY;
2094 2292
2095 hr = XmlGetText(pixn, &bstrName); 2293 hr = XmlGetText(pixn, &bstrName);
2096 if (S_FALSE == hr) 2294 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to get font name.");
2097 {
2098 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2099 }
2100 ThmExitOnFailure(hr, "Failed to get font name.");
2101 2295
2102 hr = StrAllocString(&pFont->sczFaceName, bstrName, 0); 2296 hr = StrAllocString(&pFont->sczFaceName, bstrName, 0);
2103 ThmExitOnFailure(hr, "Failed to copy font name."); 2297 ThmExitOnFailure(hr, "Failed to copy font name.");
2104 2298
2105 hr = XmlGetAttributeNumber(pixn, L"Height", reinterpret_cast<DWORD*>(&pFont->lfHeight)); 2299 hr = XmlGetAttributeInt32(pixn, L"Height", reinterpret_cast<int*>(&pFont->lfHeight));
2106 if (S_FALSE == hr) 2300 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find font height attribute.");
2107 { 2301
2108 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA); 2302 hr = XmlGetAttributeInt32(pixn, L"Weight", reinterpret_cast<int*>(&pFont->lfWeight));
2109 } 2303 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to find font weight attribute.");
2110 ThmExitOnFailure(hr, "Failed to find font height attribute.");
2111 2304
2112 hr = XmlGetAttributeNumber(pixn, L"Weight", reinterpret_cast<DWORD*>(&pFont->lfWeight)); 2305 if (!fXmlFound)
2113 if (S_FALSE == hr)
2114 { 2306 {
2115 pFont->lfWeight = FW_DONTCARE; 2307 pFont->lfWeight = FW_DONTCARE;
2116 hr = S_OK;
2117 } 2308 }
2118 ThmExitOnFailure(hr, "Failed to find font weight attribute.");
2119 2309
2120 hr = XmlGetYesNoAttribute(pixn, L"Underline", reinterpret_cast<BOOL*>(&pFont->lfUnderline)); 2310 hr = XmlGetYesNoAttribute(pixn, L"Underline", reinterpret_cast<BOOL*>(&pFont->lfUnderline));
2121 if (E_NOTFOUND == hr) 2311 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to find font underline attribute.");
2312
2313 if (!fXmlFound)
2122 { 2314 {
2123 pFont->lfUnderline = FALSE; 2315 pFont->lfUnderline = FALSE;
2124 hr = S_OK;
2125 } 2316 }
2126 ThmExitOnFailure(hr, "Failed to find font underline attribute.");
2127 2317
2128 hr = GetFontColor(pixn, L"Foreground", &crForeground, &dwSystemForegroundColor); 2318 hr = GetFontColor(pixn, L"Foreground", &crForeground, &dwSystemForegroundColor);
2129 ThmExitOnFailure(hr, "Failed to find font foreground color."); 2319 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to find font foreground color.");
2130 2320
2131 hr = GetFontColor(pixn, L"Background", &crBackground, &dwSystemBackgroundColor); 2321 hr = GetFontColor(pixn, L"Background", &crBackground, &dwSystemBackgroundColor);
2132 ThmExitOnFailure(hr, "Failed to find font background color."); 2322 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to find font background color.");
2133 2323
2134 pFont->crForeground = crForeground; 2324 pFont->crForeground = crForeground;
2135 if (THEME_INVISIBLE_COLORREF != pFont->crForeground) 2325 if (THEME_INVISIBLE_COLORREF != pFont->crForeground)
@@ -2173,16 +2363,18 @@ static HRESULT GetFontColor(
2173{ 2363{
2174 HRESULT hr = S_OK; 2364 HRESULT hr = S_OK;
2175 BSTR bstr = NULL; 2365 BSTR bstr = NULL;
2366 BOOL fXmlFound = FALSE;
2176 2367
2177 *pdwSystemColor = 0; 2368 *pdwSystemColor = 0;
2178 2369
2179 hr = XmlGetAttribute(pixn, wzAttributeName, &bstr); 2370 hr = XmlGetAttribute(pixn, wzAttributeName, &bstr);
2180 if (S_FALSE == hr) 2371 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to find font %ls color.", wzAttributeName);
2372
2373 if (!fXmlFound)
2181 { 2374 {
2182 *pColorRef = THEME_INVISIBLE_COLORREF; 2375 *pColorRef = THEME_INVISIBLE_COLORREF;
2183 ExitFunction1(hr = S_OK); 2376 ExitFunction1(hr = E_NOTFOUND);
2184 } 2377 }
2185 ThmExitOnFailure(hr, "Failed to find font %ls color.", wzAttributeName);
2186 2378
2187 if (pdwSystemColor) 2379 if (pdwSystemColor)
2188 { 2380 {
@@ -2220,7 +2412,12 @@ static HRESULT GetFontColor(
2220 } 2412 }
2221 else 2413 else
2222 { 2414 {
2223 *pColorRef = wcstoul(bstr, NULL, 16); 2415 *pColorRef = ::wcstoul(bstr, NULL, 16);
2416
2417 if (THEME_INVISIBLE_COLORREF == *pColorRef)
2418 {
2419 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Invalid %ls value: %ls.", wzAttributeName, bstr);
2420 }
2224 } 2421 }
2225 2422
2226 if (*pdwSystemColor) 2423 if (*pdwSystemColor)
@@ -2248,6 +2445,7 @@ static HRESULT ParsePages(
2248 BSTR bstrType = NULL; 2445 BSTR bstrType = NULL;
2249 THEME_PAGE* pPage = NULL; 2446 THEME_PAGE* pPage = NULL;
2250 DWORD iPage = 0; 2447 DWORD iPage = 0;
2448 BOOL fXmlFound = FALSE;
2251 2449
2252 hr = XmlSelectNodes(pElement, L"Page", &pixnl); 2450 hr = XmlSelectNodes(pElement, L"Page", &pixnl);
2253 ThmExitOnFailure(hr, "Failed to find page elements."); 2451 ThmExitOnFailure(hr, "Failed to find page elements.");
@@ -2270,11 +2468,7 @@ static HRESULT ParsePages(
2270 pPage->wId = static_cast<WORD>(iPage + 1); 2468 pPage->wId = static_cast<WORD>(iPage + 1);
2271 2469
2272 hr = XmlGetAttributeEx(pixn, L"Name", &pPage->sczName); 2470 hr = XmlGetAttributeEx(pixn, L"Name", &pPage->sczName);
2273 if (E_NOTFOUND == hr) 2471 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying page Name.");
2274 {
2275 hr = S_OK;
2276 }
2277 ThmExitOnFailure(hr, "Failed when querying page Name.");
2278 2472
2279 hr = ParseControls(hModule, wzRelativePath, pixn, pTheme, NULL, pPage); 2473 hr = ParseControls(hModule, wzRelativePath, pixn, pTheme, NULL, pPage);
2280 ThmExitOnFailure(hr, "Failed to parse page controls."); 2474 ThmExitOnFailure(hr, "Failed to parse page controls.");
@@ -2314,9 +2508,10 @@ static HRESULT ParseImageLists(
2314 IXMLDOMNode* pixnImage = NULL; 2508 IXMLDOMNode* pixnImage = NULL;
2315 DWORD dwImageListIndex = 0; 2509 DWORD dwImageListIndex = 0;
2316 DWORD dwImageCount = 0; 2510 DWORD dwImageCount = 0;
2511 THEME_IMAGELIST* pThemeImageList = NULL;
2512 BOOL fXmlFound = FALSE;
2317 HBITMAP hBitmap = NULL; 2513 HBITMAP hBitmap = NULL;
2318 BITMAP bm = { }; 2514 BITMAP bm = { };
2319 BSTR bstr = NULL;
2320 DWORD i = 0; 2515 DWORD i = 0;
2321 int iRetVal = 0; 2516 int iRetVal = 0;
2322 2517
@@ -2336,15 +2531,12 @@ static HRESULT ParseImageLists(
2336 2531
2337 while (S_OK == (hr = XmlNextElement(pixnlImageLists, &pixnImageList, NULL))) 2532 while (S_OK == (hr = XmlNextElement(pixnlImageLists, &pixnImageList, NULL)))
2338 { 2533 {
2339 hr = XmlGetAttribute(pixnImageList, L"Name", &bstr); 2534 pThemeImageList = pTheme->rgImageLists + dwImageListIndex;
2340 if (S_FALSE == hr) 2535 ++dwImageListIndex;
2341 { 2536 i = 0;
2342 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2343 }
2344 ThmExitOnFailure(hr, "Failed to find ImageList/@Name attribute.");
2345 2537
2346 hr = StrAllocString(&pTheme->rgImageLists[dwImageListIndex].sczName, bstr, 0); 2538 hr = XmlGetAttributeEx(pixnImageList, L"Name", &pThemeImageList->sczName);
2347 ThmExitOnFailure(hr, "Failed to make copy of ImageList name."); 2539 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find ImageList/@Name attribute.");
2348 2540
2349 hr = XmlSelectNodes(pixnImageList, L"Image", &pixnlImages); 2541 hr = XmlSelectNodes(pixnImageList, L"Image", &pixnlImages);
2350 ThmExitOnFailure(hr, "Failed to select child Image nodes."); 2542 ThmExitOnFailure(hr, "Failed to select child Image nodes.");
@@ -2352,38 +2544,44 @@ static HRESULT ParseImageLists(
2352 hr = pixnlImages->get_length(reinterpret_cast<long*>(&dwImageCount)); 2544 hr = pixnlImages->get_length(reinterpret_cast<long*>(&dwImageCount));
2353 ThmExitOnFailure(hr, "Failed to count the number of images in list."); 2545 ThmExitOnFailure(hr, "Failed to count the number of images in list.");
2354 2546
2355 if (0 < dwImageCount) 2547 if (!dwImageCount)
2356 { 2548 {
2357 i = 0; 2549 ThmExitOnRootFailure(hr = E_INVALIDDATA, "ImageList '%ls' has no images.", pThemeImageList->sczName);
2358 while (S_OK == (hr = XmlNextElement(pixnlImages, &pixnImage, NULL))) 2550 }
2551
2552 while (S_OK == (hr = XmlNextElement(pixnlImages, &pixnImage, NULL)))
2553 {
2554 if (hBitmap)
2359 { 2555 {
2360 if (hBitmap) 2556 ::DeleteObject(hBitmap);
2361 { 2557 hBitmap = NULL;
2362 ::DeleteObject(hBitmap); 2558 }
2363 hBitmap = NULL;
2364 }
2365 hr = ParseImage(hModule, wzRelativePath, pixnImage, &hBitmap);
2366 ThmExitOnFailure(hr, "Failed to parse image: %u", i);
2367 2559
2368 if (0 == i) 2560 hr = GetAttributeImageFileOrResource(hModule, wzRelativePath, pixnImage, &hBitmap);
2369 { 2561 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to parse image list: '%ls', item: %u", pThemeImageList->sczName, i);
2370 ::GetObjectW(hBitmap, sizeof(BITMAP), &bm);
2371 2562
2372 pTheme->rgImageLists[dwImageListIndex].hImageList = ImageList_Create(bm.bmWidth, bm.bmHeight, ILC_COLOR24, dwImageCount, 0); 2563 if (!fXmlFound)
2373 ThmExitOnNullWithLastError(pTheme->rgImageLists[dwImageListIndex].hImageList, hr, "Failed to create image list."); 2564 {
2374 } 2565 ThmExitWithRootFailure(hr, E_INVALIDDATA, "Image list: '%ls', item %u didn't specify an image.", pThemeImageList->sczName, i);
2566 }
2375 2567
2376 iRetVal = ImageList_Add(pTheme->rgImageLists[dwImageListIndex].hImageList, hBitmap, NULL); 2568 if (0 == i)
2377 if (-1 == iRetVal) 2569 {
2378 { 2570 ::GetObjectW(hBitmap, sizeof(BITMAP), &bm);
2379 ThmExitWithLastError(hr, "Failed to add image %u to image list.", i);
2380 }
2381 2571
2382 ++i; 2572 pThemeImageList->hImageList = ImageList_Create(bm.bmWidth, bm.bmHeight, ILC_COLOR24, dwImageCount, 0);
2383 ReleaseNullObject(pixnImage); 2573 ThmExitOnNullWithLastError(pThemeImageList->hImageList, hr, "Failed to create image list.");
2384 } 2574 }
2575
2576 iRetVal = ImageList_Add(pThemeImageList->hImageList, hBitmap, NULL);
2577 if (-1 == iRetVal)
2578 {
2579 ThmExitWithLastError(hr, "Failed to add image %u to image list.", i);
2580 }
2581
2582 ++i;
2583 ReleaseNullObject(pixnImage);
2385 } 2584 }
2386 ++dwImageListIndex;
2387 2585
2388 ReleaseNullObject(pixnlImages); 2586 ReleaseNullObject(pixnlImages);
2389 ReleaseNullObject(pixnImageList); 2587 ReleaseNullObject(pixnImageList);
@@ -2394,7 +2592,6 @@ LExit:
2394 { 2592 {
2395 ::DeleteObject(hBitmap); 2593 ::DeleteObject(hBitmap);
2396 } 2594 }
2397 ReleaseBSTR(bstr);
2398 ReleaseObject(pixnlImageLists); 2595 ReleaseObject(pixnlImageLists);
2399 ReleaseObject(pixnImageList); 2596 ReleaseObject(pixnImageList);
2400 ReleaseObject(pixnlImages); 2597 ReleaseObject(pixnlImages);
@@ -2572,7 +2769,7 @@ static HRESULT ParseControls(
2572 THEME_CONTROL* pControl = *prgControls + iControl; 2769 THEME_CONTROL* pControl = *prgControls + iControl;
2573 pControl->type = type; 2770 pControl->type = type;
2574 2771
2575 hr = ParseControl(hModule, wzRelativePath, pixn, pTheme, pControl, pPage); 2772 hr = ParseControl(hModule, wzRelativePath, pixn, bstrType, pTheme, pControl, pPage);
2576 ThmExitOnFailure(hr, "Failed to parse control."); 2773 ThmExitOnFailure(hr, "Failed to parse control.");
2577 2774
2578 if (pPage) 2775 if (pPage)
@@ -2608,154 +2805,108 @@ static HRESULT ParseControl(
2608 __in_opt HMODULE hModule, 2805 __in_opt HMODULE hModule,
2609 __in_opt LPCWSTR wzRelativePath, 2806 __in_opt LPCWSTR wzRelativePath,
2610 __in IXMLDOMNode* pixn, 2807 __in IXMLDOMNode* pixn,
2808 __in_z LPCWSTR wzElementName,
2611 __in THEME* pTheme, 2809 __in THEME* pTheme,
2612 __in THEME_CONTROL* pControl, 2810 __in THEME_CONTROL* pControl,
2613 __in_opt THEME_PAGE* pPage 2811 __in_opt THEME_PAGE* pPage
2614 ) 2812 )
2615{ 2813{
2616 HRESULT hr = S_OK; 2814 HRESULT hr = S_OK;
2617 BOOL fFound = FALSE; 2815 BOOL fXmlFound = FALSE;
2618 DWORD dwValue = 0; 2816 DWORD dwValue = 0;
2817 int nValue = 0;
2619 BOOL fValue = FALSE; 2818 BOOL fValue = FALSE;
2620 BSTR bstrText = NULL; 2819 BSTR bstrText = NULL;
2621 BOOL fAnyTextChildren = FALSE; 2820 BOOL fAnyTextChildren = FALSE;
2622 BOOL fAnyNoteChildren = FALSE; 2821 BOOL fAnyNoteChildren = FALSE;
2623 BOOL fSkipDimensions = FALSE;
2624 2822
2625 InitializeThemeControl(pControl); 2823 InitializeThemeControl(pControl);
2626 2824
2627 hr = XmlGetAttributeEx(pixn, L"Name", &pControl->sczName); 2825 hr = XmlGetAttributeEx(pixn, L"Name", &pControl->sczName);
2628 if (E_NOTFOUND == hr) 2826 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control Name attribute.");
2629 {
2630 hr = S_OK;
2631 }
2632 ThmExitOnFailure(hr, "Failed when querying control Name attribute.");
2633 2827
2634 hr = XmlGetAttributeEx(pixn, L"EnableCondition", &pControl->sczEnableCondition); 2828 hr = XmlGetAttributeEx(pixn, L"EnableCondition", &pControl->sczEnableCondition);
2635 if (E_NOTFOUND == hr) 2829 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control EnableCondition attribute.");
2636 {
2637 hr = S_OK;
2638 }
2639 ThmExitOnFailure(hr, "Failed when querying control EnableCondition attribute.");
2640 2830
2641 hr = XmlGetAttributeEx(pixn, L"VisibleCondition", &pControl->sczVisibleCondition); 2831 hr = XmlGetAttributeEx(pixn, L"VisibleCondition", &pControl->sczVisibleCondition);
2642 if (E_NOTFOUND == hr) 2832 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control VisibleCondition attribute.");
2643 {
2644 hr = S_OK;
2645 }
2646 ThmExitOnFailure(hr, "Failed when querying control VisibleCondition attribute.");
2647
2648 if (!fSkipDimensions)
2649 {
2650 hr = XmlGetAttributeNumber(pixn, L"X", &dwValue);
2651 if (S_FALSE == hr)
2652 {
2653 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2654 }
2655 ThmExitOnFailure(hr, "Failed to find control X attribute.");
2656 2833
2657 pControl->nX = pControl->nDefaultDpiX = dwValue; 2834 hr = GetAttributeCoordinateOrDimension(pixn, L"X", &nValue);
2835 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find control X attribute.");
2658 2836
2659 hr = XmlGetAttributeNumber(pixn, L"Y", &dwValue); 2837 pControl->nX = pControl->nDefaultDpiX = nValue;
2660 if (S_FALSE == hr)
2661 {
2662 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2663 }
2664 ThmExitOnFailure(hr, "Failed to find control Y attribute.");
2665 2838
2666 pControl->nY = pControl->nDefaultDpiY = dwValue; 2839 hr = GetAttributeCoordinateOrDimension(pixn, L"Y", &nValue);
2840 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find control Y attribute.");
2667 2841
2668 hr = XmlGetAttributeNumber(pixn, L"Height", &dwValue); 2842 pControl->nY = pControl->nDefaultDpiY = nValue;
2669 if (S_FALSE == hr)
2670 {
2671 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2672 }
2673 ThmExitOnFailure(hr, "Failed to find control Height attribute.");
2674 2843
2675 pControl->nHeight = pControl->nDefaultDpiHeight = dwValue; 2844 hr = GetAttributeCoordinateOrDimension(pixn, L"Height", &nValue);
2845 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find control Height attribute.");
2676 2846
2677 hr = XmlGetAttributeNumber(pixn, L"Width", &dwValue); 2847 pControl->nHeight = pControl->nDefaultDpiHeight = nValue;
2678 if (S_FALSE == hr)
2679 {
2680 hr = HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
2681 }
2682 ThmExitOnFailure(hr, "Failed to find control Width attribute.");
2683 2848
2684 pControl->nWidth = pControl->nDefaultDpiWidth = dwValue; 2849 hr = GetAttributeCoordinateOrDimension(pixn, L"Width", &nValue);
2685 } 2850 ThmExitOnRequiredXmlQueryFailure(hr, "Failed to find control Width attribute.");
2686 2851
2687 // Parse the optional background resource image. 2852 pControl->nWidth = pControl->nDefaultDpiWidth = nValue;
2688 hr = ParseImage(hModule, wzRelativePath, pixn, &pControl->hImage);
2689 ThmExitOnFailure(hr, "Failed while parsing control image.");
2690 2853
2691 hr = XmlGetAttributeNumber(pixn, L"SourceX", reinterpret_cast<DWORD*>(&pControl->nSourceX)); 2854 switch (pControl->type)
2692 ThmExitOnFailure(hr, "Failed when querying control SourceX attribute."); 2855 {
2856 case THEME_CONTROL_TYPE_COMMANDLINK:
2857 hr = ParseCommandLinkImage(hModule, wzRelativePath, pixn, pControl);
2858 ThmExitOnFailure(hr, "Failed while parsing CommandLink image.");
2859 break;
2860 case THEME_CONTROL_TYPE_BUTTON:
2861 case THEME_CONTROL_TYPE_IMAGE:
2862 case THEME_CONTROL_TYPE_PROGRESSBAR:
2863 hr = ParseOwnerDrawImage(hModule, wzRelativePath, pTheme, pixn, pControl);
2864 ThmExitOnFailure(hr, "Failed while parsing OwnerDraw image.");
2865 break;
2866 default:
2867 ThmExitOnUnexpectedAttribute(hr, pixn, wzElementName, L"ImageId");
2868 ThmExitOnUnexpectedAttribute(hr, pixn, wzElementName, L"ImageFile");
2869 ThmExitOnUnexpectedAttribute(hr, pixn, wzElementName, L"ImageResource");
2870 ThmExitOnUnexpectedAttribute(hr, pixn, wzElementName, L"SourceX");
2871 ThmExitOnUnexpectedAttribute(hr, pixn, wzElementName, L"SourceY");
2872 break;
2873 }
2693 2874
2694 hr = XmlGetAttributeNumber(pixn, L"SourceY", reinterpret_cast<DWORD*>(&pControl->nSourceY));
2695 ThmExitOnFailure(hr, "Failed when querying control SourceY attribute.");
2696 2875
2697 hr = XmlGetAttributeNumber(pixn, L"FontId", &pControl->dwFontId); 2876 hr = GetAttributeFontId(pixn, L"FontId", &pControl->dwFontId);
2698 ThmExitOnFailure(hr, "Failed when querying control FontId attribute."); 2877 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control FontId attribute.");
2699 2878
2700 // Parse the optional window style. 2879 // Parse the optional window style.
2701 hr = XmlGetAttributeNumberBase(pixn, L"HexStyle", 16, &pControl->dwStyle); 2880 hr = XmlGetAttributeNumberBase(pixn, L"HexStyle", 16, &pControl->dwStyle);
2702 ThmExitOnFailure(hr, "Failed when querying control HexStyle attribute."); 2881 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control HexStyle attribute.");
2703 2882
2704 // Parse the tabstop bit "shortcut nomenclature", this could have been set with the style above. 2883 // Parse the tabstop bit "shortcut nomenclature", this could have been set with the style above.
2705 hr = XmlGetYesNoAttribute(pixn, L"TabStop", &fValue); 2884 hr = XmlGetYesNoAttribute(pixn, L"TabStop", &fValue);
2706 if (E_NOTFOUND == hr) 2885 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control TabStop attribute.");
2707 {
2708 hr = S_OK;
2709 }
2710 else
2711 {
2712 ThmExitOnFailure(hr, "Failed when querying control TabStop attribute.");
2713 2886
2714 if (fValue) 2887 if (fXmlFound && fValue)
2715 { 2888 {
2716 pControl->dwStyle |= WS_TABSTOP; 2889 pControl->dwStyle |= WS_TABSTOP;
2717 }
2718 } 2890 }
2719 2891
2720 hr = XmlGetYesNoAttribute(pixn, L"Visible", &fValue); 2892 hr = XmlGetYesNoAttribute(pixn, L"Visible", &fValue);
2721 if (E_NOTFOUND == hr) 2893 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control Visible attribute.");
2722 {
2723 hr = S_OK;
2724 }
2725 else
2726 {
2727 ThmExitOnFailure(hr, "Failed when querying control Visible attribute.");
2728 2894
2729 if (fValue) 2895 if (fXmlFound && fValue)
2730 { 2896 {
2731 pControl->dwStyle |= WS_VISIBLE; 2897 pControl->dwStyle |= WS_VISIBLE;
2732 }
2733 } 2898 }
2734 2899
2735 hr = XmlGetYesNoAttribute(pixn, L"HideWhenDisabled", &fValue); 2900 hr = XmlGetYesNoAttribute(pixn, L"HideWhenDisabled", &fValue);
2736 if (E_NOTFOUND == hr) 2901 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control HideWhenDisabled attribute.");
2737 {
2738 hr = S_OK;
2739 }
2740 else
2741 {
2742 ThmExitOnFailure(hr, "Failed when querying control HideWhenDisabled attribute.");
2743 2902
2744 if (fValue) 2903 if (fXmlFound && fValue)
2745 { 2904 {
2746 pControl->dwInternalStyle |= INTERNAL_CONTROL_STYLE_HIDE_WHEN_DISABLED; 2905 pControl->dwInternalStyle |= INTERNAL_CONTROL_STYLE_HIDE_WHEN_DISABLED;
2747 }
2748 } 2906 }
2749 2907
2750 hr = XmlGetYesNoAttribute(pixn, L"DisableAutomaticBehavior", &pControl->fDisableVariableFunctionality); 2908 hr = XmlGetYesNoAttribute(pixn, L"DisableAutomaticBehavior", &pControl->fDisableVariableFunctionality);
2751 if (E_NOTFOUND == hr) 2909 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control DisableAutomaticBehavior attribute.");
2752 {
2753 hr = S_OK;
2754 }
2755 else
2756 {
2757 ThmExitOnFailure(hr, "Failed when querying control DisableAutomaticBehavior attribute.");
2758 }
2759 2910
2760 hr = ParseActions(pixn, pControl); 2911 hr = ParseActions(pixn, pControl);
2761 ThmExitOnFailure(hr, "Failed to parse action nodes of the control."); 2912 ThmExitOnFailure(hr, "Failed to parse action nodes of the control.");
@@ -2774,10 +2925,10 @@ static HRESULT ParseControl(
2774 2925
2775 if (!fAnyTextChildren && !fAnyNoteChildren) 2926 if (!fAnyTextChildren && !fAnyNoteChildren)
2776 { 2927 {
2777 hr = XmlGetAttributeNumber(pixn, L"StringId", &dwValue); 2928 hr = XmlGetAttributeUInt32(pixn, L"StringId", &dwValue);
2778 ThmExitOnOptionalXmlQueryFailure(hr, fFound, "Failed when querying control StringId attribute."); 2929 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control StringId attribute.");
2779 2930
2780 if (fFound) 2931 if (fXmlFound)
2781 { 2932 {
2782 pControl->uStringId = dwValue; 2933 pControl->uStringId = dwValue;
2783 } 2934 }
@@ -2787,9 +2938,9 @@ static HRESULT ParseControl(
2787 if (THEME_CONTROL_TYPE_BILLBOARD != pControl->type && THEME_CONTROL_TYPE_PANEL != pControl->type) 2938 if (THEME_CONTROL_TYPE_BILLBOARD != pControl->type && THEME_CONTROL_TYPE_PANEL != pControl->type)
2788 { 2939 {
2789 hr = XmlGetText(pixn, &bstrText); 2940 hr = XmlGetText(pixn, &bstrText);
2790 ThmExitOnOptionalXmlQueryFailure(hr, fFound, "Failed to get control inner text."); 2941 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get control inner text.");
2791 2942
2792 if (fFound) 2943 if (fXmlFound)
2793 { 2944 {
2794 hr = StrAllocString(&pControl->sczText, bstrText, 0); 2945 hr = StrAllocString(&pControl->sczText, bstrText, 0);
2795 ThmExitOnFailure(hr, "Failed to copy control text."); 2946 ThmExitOnFailure(hr, "Failed to copy control text.");
@@ -2803,115 +2954,93 @@ static HRESULT ParseControl(
2803 if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type) 2954 if (THEME_CONTROL_TYPE_BILLBOARD == pControl->type)
2804 { 2955 {
2805 hr = XmlGetYesNoAttribute(pixn, L"Loop", &pControl->fBillboardLoops); 2956 hr = XmlGetYesNoAttribute(pixn, L"Loop", &pControl->fBillboardLoops);
2806 if (E_NOTFOUND == hr) 2957 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying Billboard/@Loop attribute.");
2807 {
2808 hr = S_OK;
2809 }
2810 ThmExitOnFailure(hr, "Failed when querying Billboard/@Loop attribute.");
2811 2958
2812 pControl->wBillboardInterval = 5000; 2959 hr = XmlGetAttributeUInt16(pixn, L"Interval", &pControl->wBillboardInterval);
2813 hr = XmlGetAttributeNumber(pixn, L"Interval", &dwValue); 2960 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying Billboard/@Interval attribute.");
2814 if (S_OK == hr && dwValue) 2961
2962 if (!pControl->wBillboardInterval)
2815 { 2963 {
2816 pControl->wBillboardInterval = static_cast<WORD>(dwValue & 0xFFFF); 2964 pControl->wBillboardInterval = 5000;
2817 } 2965 }
2818 ThmExitOnFailure(hr, "Failed when querying Billboard/@Interval attribute.");
2819 2966
2820 hr = ParseBillboardPanels(hModule, wzRelativePath, pixn, pTheme, pControl, pPage); 2967 hr = ParseBillboardPanels(hModule, wzRelativePath, pixn, pTheme, pControl, pPage);
2821 ThmExitOnFailure(hr, "Failed to parse billboard children."); 2968 ThmExitOnFailure(hr, "Failed to parse billboard children.");
2822 } 2969 }
2823 else if (THEME_CONTROL_TYPE_COMMANDLINK == pControl->type)
2824 {
2825 hr = ParseIcon(hModule, wzRelativePath, pixn, &pControl->hIcon);
2826 ThmExitOnFailure(hr, "Failed while parsing control icon.");
2827 }
2828 else if (THEME_CONTROL_TYPE_EDITBOX == pControl->type) 2970 else if (THEME_CONTROL_TYPE_EDITBOX == pControl->type)
2829 { 2971 {
2830 hr = XmlGetYesNoAttribute(pixn, L"FileSystemAutoComplete", &fValue); 2972 hr = XmlGetYesNoAttribute(pixn, L"FileSystemAutoComplete", &fValue);
2831 if (E_NOTFOUND == hr) 2973 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying Editbox/@FileSystemAutoComplete attribute.");
2832 {
2833 hr = S_OK;
2834 }
2835 else
2836 {
2837 ThmExitOnFailure(hr, "Failed when querying Editbox/@FileSystemAutoComplete attribute.");
2838 2974
2839 if (fValue) 2975 if (fXmlFound && fValue)
2840 { 2976 {
2841 pControl->dwInternalStyle |= INTERNAL_CONTROL_STYLE_FILESYSTEM_AUTOCOMPLETE; 2977 pControl->dwInternalStyle |= INTERNAL_CONTROL_STYLE_FILESYSTEM_AUTOCOMPLETE;
2842 }
2843 } 2978 }
2844 } 2979 }
2845 else if (THEME_CONTROL_TYPE_HYPERLINK == pControl->type || THEME_CONTROL_TYPE_BUTTON == pControl->type) 2980 else if (THEME_CONTROL_TYPE_HYPERLINK == pControl->type || THEME_CONTROL_TYPE_BUTTON == pControl->type)
2846 { 2981 {
2847 hr = XmlGetAttributeNumber(pixn, L"HoverFontId", &pControl->dwFontHoverId); 2982 hr = GetAttributeFontId(pixn, L"HoverFontId", &pControl->dwFontHoverId);
2848 ThmExitOnFailure(hr, "Failed when querying control HoverFontId attribute."); 2983 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control HoverFontId attribute.");
2849 2984
2850 hr = XmlGetAttributeNumber(pixn, L"SelectedFontId", &pControl->dwFontSelectedId); 2985 hr = GetAttributeFontId(pixn, L"SelectedFontId", &pControl->dwFontSelectedId);
2851 ThmExitOnFailure(hr, "Failed when querying control SelectedFontId attribute."); 2986 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying control SelectedFontId attribute.");
2852 } 2987 }
2853 else if (THEME_CONTROL_TYPE_LABEL == pControl->type) 2988 else if (THEME_CONTROL_TYPE_LABEL == pControl->type)
2854 { 2989 {
2855 hr = XmlGetYesNoAttribute(pixn, L"Center", &fValue); 2990 hr = XmlGetYesNoAttribute(pixn, L"Center", &fValue);
2856 if (E_NOTFOUND == hr) 2991 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying Label/@Center attribute.");
2857 { 2992
2858 hr = S_OK; 2993 if (fXmlFound && fValue)
2859 }
2860 else if (fValue)
2861 { 2994 {
2862 pControl->dwStyle |= SS_CENTER; 2995 pControl->dwStyle |= SS_CENTER;
2863 } 2996 }
2864 ThmExitOnFailure(hr, "Failed when querying Label/@Center attribute.");
2865 2997
2866 hr = XmlGetYesNoAttribute(pixn, L"DisablePrefix", &fValue); 2998 hr = XmlGetYesNoAttribute(pixn, L"DisablePrefix", &fValue);
2867 if (E_NOTFOUND == hr) 2999 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying Label/@DisablePrefix attribute.");
2868 { 3000
2869 hr = S_OK; 3001 if (fXmlFound && fValue)
2870 }
2871 else if (fValue)
2872 { 3002 {
2873 pControl->dwStyle |= SS_NOPREFIX; 3003 pControl->dwStyle |= SS_NOPREFIX;
2874 } 3004 }
2875 ThmExitOnFailure(hr, "Failed when querying Label/@DisablePrefix attribute.");
2876 } 3005 }
2877 else if (THEME_CONTROL_TYPE_LISTVIEW == pControl->type) 3006 else if (THEME_CONTROL_TYPE_LISTVIEW == pControl->type)
2878 { 3007 {
2879 // Parse the optional extended window style. 3008 // Parse the optional extended window style.
2880 hr = XmlGetAttributeNumberBase(pixn, L"HexExtendedStyle", 16, &pControl->dwExtendedStyle); 3009 hr = XmlGetAttributeNumberBase(pixn, L"HexExtendedStyle", 16, &pControl->dwExtendedStyle);
2881 ThmExitOnFailure(hr, "Failed when querying ListView/@HexExtendedStyle attribute."); 3010 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying ListView/@HexExtendedStyle attribute.");
2882 3011
2883 hr = XmlGetAttribute(pixn, L"ImageList", &bstrText); 3012 hr = XmlGetAttribute(pixn, L"ImageList", &bstrText);
2884 if (S_FALSE != hr) 3013 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying ListView/@ImageList attribute.");
2885 {
2886 ThmExitOnFailure(hr, "Failed when querying ListView/@ImageList attribute.");
2887 3014
3015 if (fXmlFound)
3016 {
2888 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[0]); 3017 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[0]);
2889 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageList for ListView.", bstrText); 3018 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageList for ListView.", bstrText);
2890 } 3019 }
2891 3020
2892 hr = XmlGetAttribute(pixn, L"ImageListSmall", &bstrText); 3021 hr = XmlGetAttribute(pixn, L"ImageListSmall", &bstrText);
2893 if (S_FALSE != hr) 3022 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying ListView/@ImageListSmall attribute.");
2894 {
2895 ThmExitOnFailure(hr, "Failed when querying ListView/@ImageListSmall attribute.");
2896 3023
3024 if (fXmlFound)
3025 {
2897 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[1]); 3026 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[1]);
2898 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListSmall for ListView.", bstrText); 3027 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListSmall for ListView.", bstrText);
2899 } 3028 }
2900 3029
2901 hr = XmlGetAttribute(pixn, L"ImageListState", &bstrText); 3030 hr = XmlGetAttribute(pixn, L"ImageListState", &bstrText);
2902 if (S_FALSE != hr) 3031 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying ListView/@ImageListState attribute.");
2903 {
2904 ThmExitOnFailure(hr, "Failed when querying ListView/@ImageListState attribute.");
2905 3032
3033 if (fXmlFound)
3034 {
2906 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[2]); 3035 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[2]);
2907 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListState for ListView.", bstrText); 3036 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListState for ListView.", bstrText);
2908 } 3037 }
2909 3038
2910 hr = XmlGetAttribute(pixn, L"ImageListGroupHeader", &bstrText); 3039 hr = XmlGetAttribute(pixn, L"ImageListGroupHeader", &bstrText);
2911 if (S_FALSE != hr) 3040 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying ListView/@ImageListGroupHeader attribute.");
2912 {
2913 ThmExitOnFailure(hr, "Failed when querying ListView/@ImageListGroupHeader attribute.");
2914 3041
3042 if (fXmlFound)
3043 {
2915 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[3]); 3044 hr = FindImageList(pTheme, bstrText, &pControl->rghImageList[3]);
2916 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListGroupHeader for ListView.", bstrText); 3045 ThmExitOnFailure(hr, "Failed to find image list %ls while setting ImageListGroupHeader for ListView.", bstrText);
2917 } 3046 }
@@ -2927,11 +3056,7 @@ static HRESULT ParseControl(
2927 else if (THEME_CONTROL_TYPE_RADIOBUTTON == pControl->type) 3056 else if (THEME_CONTROL_TYPE_RADIOBUTTON == pControl->type)
2928 { 3057 {
2929 hr = XmlGetAttributeEx(pixn, L"Value", &pControl->sczValue); 3058 hr = XmlGetAttributeEx(pixn, L"Value", &pControl->sczValue);
2930 if (E_NOTFOUND == hr) 3059 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying RadioButton/@Value attribute.");
2931 {
2932 hr = S_OK;
2933 }
2934 ThmExitOnFailure(hr, "Failed when querying RadioButton/@Value attribute.");
2935 } 3060 }
2936 else if (THEME_CONTROL_TYPE_TAB == pControl->type) 3061 else if (THEME_CONTROL_TYPE_TAB == pControl->type)
2937 { 3062 {
@@ -2943,70 +3068,52 @@ static HRESULT ParseControl(
2943 pControl->dwStyle |= TVS_DISABLEDRAGDROP; 3068 pControl->dwStyle |= TVS_DISABLEDRAGDROP;
2944 3069
2945 hr = XmlGetYesNoAttribute(pixn, L"EnableDragDrop", &fValue); 3070 hr = XmlGetYesNoAttribute(pixn, L"EnableDragDrop", &fValue);
2946 if (E_NOTFOUND == hr) 3071 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying TreeView/@EnableDragDrop attribute.");
2947 { 3072
2948 hr = S_OK; 3073 if (fXmlFound && fValue)
2949 }
2950 else if (fValue)
2951 { 3074 {
2952 pControl->dwStyle &= ~TVS_DISABLEDRAGDROP; 3075 pControl->dwStyle &= ~TVS_DISABLEDRAGDROP;
2953 } 3076 }
2954 ThmExitOnFailure(hr, "Failed when querying TreeView/@EnableDragDrop attribute.");
2955 3077
2956 hr = XmlGetYesNoAttribute(pixn, L"FullRowSelect", &fValue); 3078 hr = XmlGetYesNoAttribute(pixn, L"FullRowSelect", &fValue);
2957 if (E_NOTFOUND == hr) 3079 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying TreeView/@FullRowSelect attribute.");
2958 { 3080
2959 hr = S_OK; 3081 if (fXmlFound && fValue)
2960 }
2961 else if (fValue)
2962 { 3082 {
2963 pControl->dwStyle |= TVS_FULLROWSELECT; 3083 pControl->dwStyle |= TVS_FULLROWSELECT;
2964 } 3084 }
2965 ThmExitOnFailure(hr, "Failed when querying TreeView/@FullRowSelect attribute.");
2966 3085
2967 hr = XmlGetYesNoAttribute(pixn, L"HasButtons", &fValue); 3086 hr = XmlGetYesNoAttribute(pixn, L"HasButtons", &fValue);
2968 if (E_NOTFOUND == hr) 3087 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying TreeView/@HasButtons attribute.");
2969 { 3088
2970 hr = S_OK; 3089 if (fXmlFound && fValue)
2971 }
2972 else if (fValue)
2973 { 3090 {
2974 pControl->dwStyle |= TVS_HASBUTTONS; 3091 pControl->dwStyle |= TVS_HASBUTTONS;
2975 } 3092 }
2976 ThmExitOnFailure(hr, "Failed when querying TreeView/@HasButtons attribute.");
2977 3093
2978 hr = XmlGetYesNoAttribute(pixn, L"AlwaysShowSelect", &fValue); 3094 hr = XmlGetYesNoAttribute(pixn, L"AlwaysShowSelect", &fValue);
2979 if (E_NOTFOUND == hr) 3095 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying TreeView/@AlwaysShowSelect attribute.");
2980 { 3096
2981 hr = S_OK; 3097 if (fXmlFound && fValue)
2982 }
2983 else if (fValue)
2984 { 3098 {
2985 pControl->dwStyle |= TVS_SHOWSELALWAYS; 3099 pControl->dwStyle |= TVS_SHOWSELALWAYS;
2986 } 3100 }
2987 ThmExitOnFailure(hr, "Failed when querying TreeView/@AlwaysShowSelect attribute.");
2988 3101
2989 hr = XmlGetYesNoAttribute(pixn, L"LinesAtRoot", &fValue); 3102 hr = XmlGetYesNoAttribute(pixn, L"LinesAtRoot", &fValue);
2990 if (E_NOTFOUND == hr) 3103 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying TreeView/@LinesAtRoot attribute.");
2991 { 3104
2992 hr = S_OK; 3105 if (fXmlFound && fValue)
2993 }
2994 else if (fValue)
2995 { 3106 {
2996 pControl->dwStyle |= TVS_LINESATROOT; 3107 pControl->dwStyle |= TVS_LINESATROOT;
2997 } 3108 }
2998 ThmExitOnFailure(hr, "Failed when querying TreeView/@LinesAtRoot attribute.");
2999 3109
3000 hr = XmlGetYesNoAttribute(pixn, L"HasLines", &fValue); 3110 hr = XmlGetYesNoAttribute(pixn, L"HasLines", &fValue);
3001 if (E_NOTFOUND == hr) 3111 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed when querying TreeView/@HasLines attribute.");
3002 { 3112
3003 hr = S_OK; 3113 if (fXmlFound && fValue)
3004 }
3005 else if (fValue)
3006 { 3114 {
3007 pControl->dwStyle |= TVS_HASLINES; 3115 pControl->dwStyle |= TVS_HASLINES;
3008 } 3116 }
3009 ThmExitOnFailure(hr, "Failed when querying TreeView/@HasLines attribute.");
3010 } 3117 }
3011 3118
3012LExit: 3119LExit:
@@ -3188,7 +3295,8 @@ static HRESULT ParseColumns(
3188 IXMLDOMNodeList* pixnl = NULL; 3295 IXMLDOMNodeList* pixnl = NULL;
3189 IXMLDOMNode* pixnChild = NULL; 3296 IXMLDOMNode* pixnChild = NULL;
3190 BSTR bstrText = NULL; 3297 BSTR bstrText = NULL;
3191 DWORD dwValue = 0; 3298 int nValue = 0;
3299 BOOL fXmlFound = FALSE;
3192 3300
3193 hr = XmlSelectNodes(pixn, L"Column", &pixnl); 3301 hr = XmlSelectNodes(pixn, L"Column", &pixnl);
3194 ThmExitOnFailure(hr, "Failed to select child column nodes."); 3302 ThmExitOnFailure(hr, "Failed to select child column nodes.");
@@ -3209,21 +3317,18 @@ static HRESULT ParseColumns(
3209 hr = XmlGetText(pixnChild, &bstrText); 3317 hr = XmlGetText(pixnChild, &bstrText);
3210 ThmExitOnFailure(hr, "Failed to get inner text of column element."); 3318 ThmExitOnFailure(hr, "Failed to get inner text of column element.");
3211 3319
3212 hr = XmlGetAttributeNumber(pixnChild, L"Width", &dwValue); 3320 hr = GetAttributeCoordinateOrDimension(pixnChild, L"Width", &nValue);
3213 if (S_FALSE == hr) 3321 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get column width attribute.");
3322
3323 if (!fXmlFound)
3214 { 3324 {
3215 dwValue = 100; 3325 nValue = 100;
3216 } 3326 }
3217 ThmExitOnFailure(hr, "Failed to get column width attribute.");
3218 3327
3219 pColumn->nBaseWidth = pColumn->nDefaultDpiBaseWidth = dwValue; 3328 pColumn->nBaseWidth = pColumn->nDefaultDpiBaseWidth = nValue;
3220 3329
3221 hr = XmlGetYesNoAttribute(pixnChild, L"Expands", reinterpret_cast<BOOL*>(&pColumn->fExpands)); 3330 hr = XmlGetYesNoAttribute(pixnChild, L"Expands", &pColumn->fExpands);
3222 if (E_NOTFOUND == hr) 3331 ThmExitOnOptionalXmlQueryFailure(hr, fXmlFound, "Failed to get expands attribute.");
3223 {
3224 hr = S_OK;
3225 }
3226 ThmExitOnFailure(hr, "Failed to get expands attribute.");
3227 3332
3228 hr = StrAllocString(&pColumn->pszName, bstrText, 0); 3333 hr = StrAllocString(&pColumn->pszName, bstrText, 0);
3229 ThmExitOnFailure(hr, "Failed to copy column name."); 3334 ThmExitOnFailure(hr, "Failed to copy column name.");
@@ -3305,7 +3410,7 @@ static HRESULT ParseRadioButtons(
3305 pControl->type = THEME_CONTROL_TYPE_RADIOBUTTON; 3410 pControl->type = THEME_CONTROL_TYPE_RADIOBUTTON;
3306 *pcControls += 1; 3411 *pcControls += 1;
3307 3412
3308 hr = ParseControl(hModule, wzRelativePath, pixnChild, pTheme, pControl, pPage); 3413 hr = ParseControl(hModule, wzRelativePath, pixnChild, L"RadioButton", pTheme, pControl, pPage);
3309 ThmExitOnFailure(hr, "Failed to parse control."); 3414 ThmExitOnFailure(hr, "Failed to parse control.");
3310 3415
3311 if (fFirst) 3416 if (fFirst)
@@ -3472,7 +3577,7 @@ static HRESULT ParseTooltips(
3472 __in IXMLDOMNode* pixn, 3577 __in IXMLDOMNode* pixn,
3473 __in THEME_CONTROL* pControl, 3578 __in THEME_CONTROL* pControl,
3474 __inout BOOL* pfAnyChildren 3579 __inout BOOL* pfAnyChildren
3475) 3580 )
3476{ 3581{
3477 HRESULT hr = S_OK; 3582 HRESULT hr = S_OK;
3478 IXMLDOMNode* pixnChild = NULL; 3583 IXMLDOMNode* pixnChild = NULL;
@@ -3503,6 +3608,32 @@ LExit:
3503} 3608}
3504 3609
3505 3610
3611static HRESULT ParseUnexpectedAttribute(
3612 __in IXMLDOMNode* pixn,
3613 __in_z LPCWSTR wzElementName,
3614 __in_z LPCWSTR wzAttribute
3615 )
3616{
3617 HRESULT hr = S_OK;
3618 BSTR bstr = NULL;
3619
3620 hr = XmlGetAttribute(pixn, wzAttribute, &bstr);
3621 ThmExitOnFailure(hr, "Failed to get attribute %ls/@%ls", wzElementName, wzAttribute);
3622
3623 if (S_OK == hr)
3624 {
3625 ThmExitOnRootFailure(hr = E_INVALIDDATA, "Element '%ls' has unexpected attribute '%ls', value: %ls.", wzElementName, wzAttribute, bstr);
3626 }
3627
3628 hr = S_OK;
3629
3630LExit:
3631 ReleaseBSTR(bstr);
3632
3633 return hr;
3634}
3635
3636
3506static HRESULT ParseNotes( 3637static HRESULT ParseNotes(
3507 __in IXMLDOMNode* pixn, 3638 __in IXMLDOMNode* pixn,
3508 __in THEME_CONTROL* pControl, 3639 __in THEME_CONTROL* pControl,