Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

825 lines
22 KiB

  1. //-------------------------------------------------------------------------
  2. // TmUtils.cpp - theme manager shared utilities
  3. //-------------------------------------------------------------------------
  4. #include "stdafx.h"
  5. #include "TmUtils.h"
  6. #include "ThemeFile.h"
  7. #include "loader.h"
  8. //-------------------------------------------------------------------------
  9. //---------------------------------------------------------------------------
  10. //---------------------------------------------------------------------------
  11. CMemoryDC::CMemoryDC()
  12. {
  13. _hBitmap = NULL;
  14. _hdc = NULL;
  15. _hOldBitmap = NULL;
  16. }
  17. //-------------------------------------------------------------------------
  18. CMemoryDC::~CMemoryDC()
  19. {
  20. CloseDC();
  21. }
  22. //-------------------------------------------------------------------------
  23. HRESULT CMemoryDC::OpenDC(HDC hdcSource, int iWidth, int iHeight)
  24. {
  25. HRESULT hr;
  26. BOOL fDeskDC = FALSE;
  27. if (! hdcSource)
  28. {
  29. hdcSource = GetWindowDC(NULL);
  30. if (! hdcSource)
  31. {
  32. hr = MakeErrorLast();
  33. goto exit;
  34. }
  35. fDeskDC = TRUE;
  36. }
  37. _hBitmap = CreateCompatibleBitmap(hdcSource, iWidth, iHeight);
  38. if (! _hBitmap)
  39. {
  40. hr = MakeErrorLast();
  41. goto exit;
  42. }
  43. _hdc = CreateCompatibleDC(hdcSource);
  44. if (! _hdc)
  45. {
  46. hr = MakeErrorLast();
  47. goto exit;
  48. }
  49. _hOldBitmap = (HBITMAP) SelectObject(_hdc, _hBitmap);
  50. if (! _hOldBitmap)
  51. {
  52. hr = MakeErrorLast();
  53. goto exit;
  54. }
  55. hr = S_OK;
  56. exit:
  57. if (fDeskDC)
  58. ReleaseDC(NULL, hdcSource);
  59. if (FAILED(hr))
  60. CloseDC();
  61. return hr;
  62. }
  63. //-------------------------------------------------------------------------
  64. void CMemoryDC::CloseDC()
  65. {
  66. if (_hOldBitmap)
  67. {
  68. SelectObject(_hdc, _hOldBitmap);
  69. _hOldBitmap = NULL;
  70. }
  71. if (_hdc)
  72. {
  73. DeleteDC(_hdc);
  74. _hdc = NULL;
  75. }
  76. if (_hBitmap)
  77. {
  78. DeleteObject(_hBitmap);
  79. _hBitmap = NULL;
  80. }
  81. }
  82. //-------------------------------------------------------------------------
  83. //-------------------------------------------------------------------------
  84. //-------------------------------------------------------------------------
  85. CBitmapPixels::CBitmapPixels()
  86. {
  87. _hdrBitmap = NULL;
  88. _buffer = NULL;
  89. _iWidth = 0;
  90. _iHeight = 0;
  91. }
  92. //-------------------------------------------------------------------------
  93. CBitmapPixels::~CBitmapPixels()
  94. {
  95. if (_buffer)
  96. delete [] (BYTE *)_buffer;
  97. }
  98. //-------------------------------------------------------------------------
  99. BYTE* CBitmapPixels::Buffer()
  100. {
  101. return _buffer;
  102. }
  103. //-------------------------------------------------------------------------
  104. HRESULT CBitmapPixels::OpenBitmap(HDC hdc, HBITMAP bitmap, BOOL fForceRGB32,
  105. DWORD OUT **pPixels, OPTIONAL OUT int *piWidth, OPTIONAL OUT int *piHeight,
  106. OPTIONAL OUT int *piBytesPerPixel, OPTIONAL OUT int *piBytesPerRow,
  107. OPTIONAL OUT int *piPreviousBytesPerPixel, OPTIONAL UINT cbBytesBefore)
  108. {
  109. if (! pPixels)
  110. return MakeError32(E_INVALIDARG);
  111. bool fNeedRelease = false;
  112. if (! hdc)
  113. {
  114. hdc = GetWindowDC(NULL);
  115. if (! hdc)
  116. {
  117. return MakeErrorLast();
  118. }
  119. fNeedRelease = true;
  120. }
  121. BITMAP bminfo;
  122. GetObject(bitmap, sizeof(bminfo), &bminfo);
  123. _iWidth = bminfo.bmWidth;
  124. _iHeight = bminfo.bmHeight;
  125. int iBytesPerPixel;
  126. if (piPreviousBytesPerPixel != NULL)
  127. {
  128. *piPreviousBytesPerPixel = bminfo.bmBitsPixel / 8;
  129. }
  130. if ((fForceRGB32) || (bminfo.bmBitsPixel == 32))
  131. iBytesPerPixel = 4;
  132. else
  133. iBytesPerPixel = 3;
  134. int iRawBytes = _iWidth * iBytesPerPixel;
  135. int iBytesPerRow = 4*((iRawBytes+3)/4);
  136. int size = sizeof(BITMAPINFOHEADER) + _iHeight*iBytesPerRow;
  137. _buffer = new BYTE[size + cbBytesBefore + 100]; // avoid random GetDIBits() failures with 100 bytes padding (?)
  138. if (! _buffer)
  139. return MakeError32(E_OUTOFMEMORY);
  140. _hdrBitmap = (BITMAPINFOHEADER *)(_buffer + cbBytesBefore);
  141. memset(_hdrBitmap, 0, sizeof(BITMAPINFOHEADER));
  142. _hdrBitmap->biSize = sizeof(BITMAPINFOHEADER);
  143. _hdrBitmap->biWidth = _iWidth;
  144. _hdrBitmap->biHeight = _iHeight;
  145. _hdrBitmap->biPlanes = 1;
  146. _hdrBitmap->biBitCount = static_cast<WORD>(8*iBytesPerPixel);
  147. _hdrBitmap->biCompression = BI_RGB;
  148. #ifdef DEBUG
  149. int linecnt =
  150. #endif
  151. GetDIBits(hdc, bitmap, 0, _iHeight, DIBDATA(_hdrBitmap), (BITMAPINFO *)_hdrBitmap,
  152. DIB_RGB_COLORS);
  153. ATLASSERT(linecnt == _iHeight);
  154. if (fNeedRelease)
  155. ReleaseDC(NULL, hdc);
  156. *pPixels = (DWORD *)DIBDATA(_hdrBitmap);
  157. if (piWidth)
  158. *piWidth = _iWidth;
  159. if (piHeight)
  160. *piHeight = _iHeight;
  161. if (piBytesPerPixel)
  162. *piBytesPerPixel = iBytesPerPixel;
  163. if (piBytesPerRow)
  164. *piBytesPerRow = iBytesPerRow;
  165. return S_OK;
  166. }
  167. //-------------------------------------------------------------------------
  168. void CBitmapPixels::CloseBitmap(HDC hdc, HBITMAP hBitmap)
  169. {
  170. if (_hdrBitmap && _buffer)
  171. {
  172. if (hBitmap) // rewrite bitmap
  173. {
  174. bool fNeedRelease = false;
  175. if (! hdc)
  176. {
  177. hdc = GetWindowDC(NULL);
  178. fNeedRelease = true;
  179. }
  180. SetDIBits(hdc, hBitmap, 0, _iHeight, DIBDATA(_hdrBitmap), (BITMAPINFO *)_hdrBitmap,
  181. DIB_RGB_COLORS);
  182. if ((fNeedRelease) && (hdc))
  183. ReleaseDC(NULL, hdc);
  184. }
  185. delete [] (BYTE *)_buffer;
  186. _hdrBitmap = NULL;
  187. _buffer = NULL;
  188. }
  189. }
  190. //-------------------------------------------------------------------------
  191. //---------------------------------------------------------------------------
  192. //---------------------------------------------------------------------------
  193. HRESULT LoadThemeLibrary(LPCWSTR pszThemeName, HINSTANCE *phInst)
  194. {
  195. HRESULT hr = S_OK;
  196. HINSTANCE hInst = NULL;
  197. hInst = LoadLibraryEx(pszThemeName, NULL, LOAD_LIBRARY_AS_DATAFILE);
  198. if (! hInst)
  199. {
  200. hr = MakeErrorLast();
  201. goto exit;
  202. }
  203. //---- is this version supported? ----
  204. void *pvVersion;
  205. DWORD dwVersionLength;
  206. hr = GetPtrToResource(hInst, L"PACKTHEM_VERSION", MAKEINTRESOURCE(1), &pvVersion, &dwVersionLength);
  207. if (SUCCEEDED(hr))
  208. {
  209. if (dwVersionLength != sizeof(SHORT))
  210. hr = E_FAIL;
  211. else
  212. {
  213. SHORT sVersionNum = *(SHORT *)pvVersion;
  214. if (sVersionNum != PACKTHEM_VERSION)
  215. hr = E_FAIL;
  216. }
  217. }
  218. if (FAILED(hr))
  219. {
  220. hr = MakeError32(ERROR_BAD_FORMAT);
  221. goto exit;
  222. }
  223. *phInst = hInst;
  224. exit:
  225. if (FAILED(hr))
  226. {
  227. if (hInst)
  228. FreeLibrary(hInst);
  229. }
  230. return hr;
  231. }
  232. //---------------------------------------------------------------------------
  233. LPCWSTR ThemeString(CUxThemeFile *pThemeFile, int iOffset)
  234. {
  235. LPCWSTR p = L"";
  236. if ((pThemeFile) && (pThemeFile->_pbThemeData) && (iOffset > 0))
  237. {
  238. p = (LPCWSTR) (pThemeFile->_pbThemeData + iOffset);
  239. }
  240. return p;
  241. }
  242. //---------------------------------------------------------------------------
  243. int GetLoadIdFromTheme(CUxThemeFile *pThemeFile)
  244. {
  245. int iLoadId = 0;
  246. if (pThemeFile)
  247. {
  248. THEMEHDR *hdr = (THEMEHDR *)pThemeFile->_pbThemeData;
  249. iLoadId = hdr->iLoadId;
  250. }
  251. return iLoadId;
  252. }
  253. //---------------------------------------------------------------------------
  254. HRESULT GetThemeNameId(CUxThemeFile *pThemeFile, LPWSTR pszFileNameBuff, UINT cchFileNameBuff,
  255. LPWSTR pszColorParam, UINT cchColorParam, LPWSTR pszSizeParam, UINT cchSizeParam, int *piSysMetricsOffset, LANGID *pwLangID)
  256. {
  257. HRESULT hr = S_OK;
  258. THEMEHDR *hdr = (THEMEHDR *)pThemeFile->_pbThemeData;
  259. if (piSysMetricsOffset)
  260. *piSysMetricsOffset = hdr->iSysMetricsOffset;
  261. if (pszFileNameBuff)
  262. {
  263. hr = hr_lstrcpy(pszFileNameBuff, ThemeString(pThemeFile, hdr->iDllNameOffset), cchFileNameBuff);
  264. }
  265. if (SUCCEEDED(hr) && pszColorParam)
  266. {
  267. hr = hr_lstrcpy(pszColorParam, ThemeString(pThemeFile, hdr->iColorParamOffset), cchColorParam);
  268. }
  269. if (SUCCEEDED(hr) && pszSizeParam)
  270. {
  271. hr = hr_lstrcpy(pszSizeParam, ThemeString(pThemeFile, hdr->iSizeParamOffset), cchSizeParam);
  272. }
  273. if (SUCCEEDED(hr) && pwLangID)
  274. *pwLangID = (LANGID) hdr->dwLangID;
  275. return hr;
  276. }
  277. //---------------------------------------------------------------------------
  278. BOOL ThemeMatch (CUxThemeFile *pThemeFile, LPCWSTR pszThemeName, LPCWSTR pszColorName, LPCWSTR pszSizeName, LANGID wLangID)
  279. {
  280. WCHAR szThemeFileName[MAX_PATH];
  281. WCHAR szColorParam[MAX_PATH];
  282. WCHAR szSizeParam[MAX_PATH];
  283. LANGID wThemeLangID = 0;
  284. bool bLangMatch = true;
  285. HRESULT hr = GetThemeNameId(pThemeFile,
  286. szThemeFileName, ARRAYSIZE(szThemeFileName),
  287. szColorParam, ARRAYSIZE(szColorParam),
  288. szSizeParam, ARRAYSIZE(szSizeParam), NULL, &wThemeLangID);
  289. if (wLangID != 0 && ((wThemeLangID != wLangID) || (wLangID != GetUserDefaultUILanguage())))
  290. {
  291. Log(LOG_TMLOAD, L"UxTheme: Reloading theme because of language change.");
  292. Log(LOG_TMLOAD, L"UxTheme: User LangID=0x%x, current theme=0x%x, LastUserLangID=0x%x", GetUserDefaultUILanguage(), wThemeLangID, wLangID);
  293. bLangMatch = false;
  294. }
  295. return(SUCCEEDED(hr) &&
  296. (lstrcmpiW(pszThemeName, szThemeFileName) == 0) &&
  297. (lstrcmpiW(pszColorName, szColorParam) == 0) &&
  298. (lstrcmpiW(pszSizeName, szSizeParam) == 0) &&
  299. bLangMatch);
  300. }
  301. //---------------------------------------------------------------------------
  302. HRESULT GetColorSchemeIndex(HINSTANCE hInst, LPCWSTR pszColor, int *piIndex)
  303. {
  304. HRESULT hr;
  305. WCHAR szColor[_MAX_PATH+1];
  306. for (int i=0; i < 1000; i++)
  307. {
  308. hr = GetResString(hInst, L"COLORNAMES", i, szColor, ARRAYSIZE(szColor));
  309. if (FAILED(hr))
  310. break;
  311. if (lstrcmpi(pszColor, szColor)==0)
  312. {
  313. *piIndex = i;
  314. return S_OK;
  315. }
  316. }
  317. return MakeError32(ERROR_NOT_FOUND); // not found
  318. }
  319. //---------------------------------------------------------------------------
  320. HRESULT GetSizeIndex(HINSTANCE hInst, LPCWSTR pszSize, int *piIndex)
  321. {
  322. HRESULT hr;
  323. WCHAR szSize[_MAX_PATH+1];
  324. for (int i=0; i < 1000; i++)
  325. {
  326. hr = GetResString(hInst, L"SIZENAMES", i, szSize, ARRAYSIZE(szSize));
  327. if (FAILED(hr))
  328. break;
  329. if (lstrcmpi(pszSize, szSize)==0)
  330. {
  331. *piIndex = i;
  332. return S_OK;
  333. }
  334. }
  335. return MakeError32(ERROR_NOT_FOUND); // not found
  336. }
  337. //---------------------------------------------------------------------------
  338. HRESULT FindComboData(HINSTANCE hDll, COLORSIZECOMBOS **ppCombos)
  339. {
  340. HRSRC hRsc = FindResource(hDll, L"COMBO", L"COMBODATA");
  341. if (! hRsc)
  342. return MakeErrorLast();
  343. HGLOBAL hGlobal = LoadResource(hDll, hRsc);
  344. if (! hGlobal)
  345. return MakeErrorLast();
  346. *ppCombos = (COLORSIZECOMBOS *)LockResource(hGlobal);
  347. if (! *ppCombos)
  348. return MakeErrorLast();
  349. return S_OK;
  350. }
  351. //---------------------------------------------------------------------------
  352. BOOL FormatLocalMsg(HINSTANCE hInst, int iStringNum,
  353. LPWSTR pszMessageBuff, DWORD dwMaxMessageChars, DWORD *pdwParams, TMERRINFO *pErrInfo)
  354. {
  355. BOOL fGotMsg = FALSE;
  356. WCHAR szBuff[_MAX_PATH+1];
  357. WCHAR *p;
  358. //----- get string from string table ----
  359. if (LoadString(hInst, iStringNum, szBuff, ARRAYSIZE(szBuff)))
  360. {
  361. //---- repl %1 or %2 with %s ----
  362. p = szBuff;
  363. while (*p)
  364. {
  365. if (*p == '%')
  366. {
  367. p++;
  368. if ((*p == '1') || (*p == '2'))
  369. *p = 's';
  370. p++;
  371. }
  372. else
  373. p++;
  374. }
  375. int len = lstrlen(szBuff);
  376. if (len)
  377. {
  378. wsprintf(pszMessageBuff, szBuff, pErrInfo->szMsgParam1, pErrInfo->szMsgParam2);
  379. fGotMsg = TRUE;
  380. }
  381. }
  382. return fGotMsg;
  383. }
  384. //---------------------------------------------------------------------------
  385. HRESULT _FormatParseMessage(TMERRINFO *pErrInfo,
  386. OUT LPWSTR pszMessageBuff, DWORD dwMaxMessageChars)
  387. {
  388. LogEntry(L"_FormatParseMessage");
  389. HRESULT hr = S_OK;
  390. DWORD dwParams[] = {PtrToInt(pErrInfo->szMsgParam1), PtrToInt(pErrInfo->szMsgParam2)};
  391. DWORD dwCode = pErrInfo->dwParseErrCode;
  392. BOOL fGotMsg = FALSE;
  393. int iStringNum = SCODE_CODE(dwCode);
  394. //---- get process name (see if we are "packthem.exe" ----
  395. WCHAR szPath[MAX_PATH];
  396. if (! GetModuleFileNameW( NULL, szPath, ARRAYSIZE(szPath) ))
  397. goto exit;
  398. WCHAR szDrive[_MAX_DRIVE], szDir[_MAX_DIR], szBase[_MAX_FNAME], szExt[_MAX_EXT];
  399. _wsplitpath(szPath, szDrive, szDir, szBase, szExt);
  400. if (lstrcmpi(szBase, L"packthem")==0) // give packthem priority
  401. {
  402. fGotMsg = FormatLocalMsg(GetModuleHandle(NULL), iStringNum,
  403. pszMessageBuff, dwMaxMessageChars, dwParams, pErrInfo);
  404. }
  405. if (! fGotMsg) // try normal route: uxtheme.dll
  406. {
  407. HINSTANCE hInst = LoadLibrary(L"uxtheme.dll");
  408. if (! hInst)
  409. {
  410. Log(LOG_ALWAYS, L"_FormatParseMessage: Could not load uxtheme.dll");
  411. hr = E_FAIL;
  412. goto exit;
  413. }
  414. fGotMsg = FormatLocalMsg(hInst, iStringNum,
  415. pszMessageBuff, dwMaxMessageChars, dwParams, pErrInfo);
  416. FreeLibrary(hInst);
  417. }
  418. if (! fGotMsg)
  419. hr = MakeErrorLast();
  420. exit:
  421. LogExit(L"_FormatParseMessage");
  422. return hr;
  423. }
  424. //---------------------------------------------------------------------------
  425. HRESULT _GetThemeParseErrorInfo(OUT PARSE_ERROR_INFO *pInfo)
  426. {
  427. LogEntry(L"_GetThemeParseErrorInfo");
  428. HRESULT hr = S_OK;
  429. if (pInfo->dwSize != sizeof(PARSE_ERROR_INFO)) // unsupported size
  430. {
  431. hr = MakeError32(E_INVALIDARG);
  432. goto exit;
  433. }
  434. TMERRINFO *pErrInfo = GetParseErrorInfo(TRUE);
  435. if (! pErrInfo)
  436. {
  437. hr = MakeError32(E_OUTOFMEMORY);
  438. goto exit;
  439. }
  440. //---- convert code into msg using param strings ----
  441. hr = _FormatParseMessage(pErrInfo, pInfo->szMsg, ARRAYSIZE(pInfo->szMsg));
  442. if (FAILED(hr))
  443. goto exit;
  444. //---- transfer the other info ----
  445. pInfo->dwParseErrCode = pErrInfo->dwParseErrCode;
  446. pInfo->iLineNum = pErrInfo->iLineNum;
  447. lstrcpy_truncate(pInfo->szFileName, pErrInfo->szFileName, ARRAYSIZE(pInfo->szFileName));
  448. lstrcpy_truncate(pInfo->szSourceLine, pErrInfo->szSourceLine, ARRAYSIZE(pInfo->szSourceLine));
  449. exit:
  450. LogExit(L"_GetThemeParseErrorInfo");
  451. return hr;
  452. }
  453. //---------------------------------------------------------------------------
  454. HRESULT _ParseThemeIniFile(LPCWSTR pszFileName,
  455. DWORD dwParseFlags, OPTIONAL THEMEENUMPROC pfnCallBack, OPTIONAL LPARAM lparam)
  456. {
  457. LogEntry(L"ParseThemeIniFile");
  458. HRESULT hr;
  459. CThemeParser *pParser = new CThemeParser;
  460. if (! pParser)
  461. {
  462. hr = MakeError32(E_OUTOFMEMORY);
  463. goto exit;
  464. }
  465. hr = pParser->ParseThemeFile(pszFileName, NULL, NULL, pfnCallBack, lparam,
  466. dwParseFlags);
  467. delete pParser;
  468. exit:
  469. LogExit(L"ParseThemeIniFile");
  470. return hr;
  471. }
  472. //---------------------------------------------------------------------------
  473. BOOL ThemeLibStartUp(BOOL fThreadAttach)
  474. {
  475. BOOL fInit = FALSE;
  476. if (fThreadAttach)
  477. {
  478. //---- nothing to do here ----
  479. }
  480. else // process
  481. {
  482. _tls_ErrorInfoIndex = TlsAlloc();
  483. if (_tls_ErrorInfoIndex == (DWORD)-1)
  484. goto exit;
  485. if (! LogStartUp())
  486. goto exit;
  487. if (! UtilsStartUp())
  488. goto exit;
  489. }
  490. fInit = TRUE;
  491. exit:
  492. return fInit;
  493. }
  494. //---------------------------------------------------------------------------
  495. BOOL ThemeLibShutDown(BOOL fThreadDetach)
  496. {
  497. if (fThreadDetach)
  498. {
  499. //---- destroy the thread-local Error Info ----
  500. TMERRINFO * ei = GetParseErrorInfo(FALSE);
  501. if (ei)
  502. {
  503. TlsSetValue(_tls_ErrorInfoIndex, NULL);
  504. delete ei;
  505. }
  506. }
  507. else // process
  508. {
  509. UtilsShutDown();
  510. LogShutDown();
  511. if (_tls_ErrorInfoIndex != (DWORD)-1)
  512. {
  513. TlsFree(_tls_ErrorInfoIndex);
  514. _tls_ErrorInfoIndex = (DWORD)-1;
  515. }
  516. }
  517. return TRUE;
  518. }
  519. //---------------------------------------------------------------------------
  520. HRESULT GetThemeSizeId(int iSysSizeId, int *piThemeSizeId)
  521. {
  522. HRESULT hr = S_OK;
  523. *piThemeSizeId = 0;
  524. switch (iSysSizeId)
  525. {
  526. case SM_CXSIZEFRAME:
  527. *piThemeSizeId = TMT_SIZINGBORDERWIDTH;
  528. break;
  529. case SM_CYSIZEFRAME:
  530. *piThemeSizeId = TMT_SIZINGBORDERWIDTH;
  531. break;
  532. case SM_CXVSCROLL:
  533. *piThemeSizeId = TMT_SCROLLBARWIDTH;
  534. break;
  535. case SM_CYHSCROLL:
  536. *piThemeSizeId = TMT_SCROLLBARHEIGHT;
  537. break;
  538. case SM_CXSIZE:
  539. *piThemeSizeId = TMT_CAPTIONBARWIDTH;
  540. break;
  541. case SM_CYSIZE:
  542. *piThemeSizeId = TMT_CAPTIONBARHEIGHT;
  543. break;
  544. case SM_CXSMSIZE:
  545. *piThemeSizeId = TMT_SMCAPTIONBARWIDTH;
  546. break;
  547. case SM_CYSMSIZE:
  548. *piThemeSizeId = TMT_SMCAPTIONBARHEIGHT;
  549. break;
  550. case SM_CXMENUSIZE:
  551. *piThemeSizeId = TMT_MENUBARWIDTH;
  552. break;
  553. case SM_CYMENUSIZE:
  554. *piThemeSizeId = TMT_MENUBARHEIGHT;
  555. break;
  556. default:
  557. hr = MakeError32(E_INVALIDARG);
  558. break;
  559. }
  560. return hr;
  561. }
  562. //---------------------------------------------------------------------------
  563. HRESULT _EnumThemeSizes(HINSTANCE hInst, LPCWSTR pszThemeName,
  564. OPTIONAL LPCWSTR pszColorScheme, DWORD dwSizeIndex, OUT THEMENAMEINFO *ptn, BOOL fCheckColorDepth)
  565. {
  566. HRESULT hr;
  567. COLORSIZECOMBOS *combos;
  568. hr = FindComboData(hInst, &combos);
  569. if (FAILED(hr))
  570. goto exit;
  571. int iMinColor, iMaxColor;
  572. iMinColor = 0;
  573. iMaxColor = combos->cColorSchemes-1;
  574. if (pszColorScheme) // translate "pszColorScheme" into a color number
  575. {
  576. int index;
  577. hr = GetColorSchemeIndex(hInst, pszColorScheme, &index);
  578. if (FAILED(hr))
  579. goto exit;
  580. //---- restrict our search to just this color ----
  581. iMinColor = index;
  582. iMaxColor = index;
  583. }
  584. int s, c;
  585. DWORD dwSizeNum;
  586. dwSizeNum = 0;
  587. BOOL gotall;
  588. gotall = FALSE;
  589. DWORD dwCurMinDepth = 0;
  590. if (fCheckColorDepth)
  591. {
  592. dwCurMinDepth = MinimumDisplayColorDepth();
  593. }
  594. for (s=0; s < combos->cSizes; s++)
  595. {
  596. BOOL fFoundOne = FALSE;
  597. for (c=iMinColor; c <= iMaxColor; c++)
  598. {
  599. if (COMBOENTRY(combos, c, s) != -1)
  600. {
  601. fFoundOne = TRUE;
  602. break;
  603. }
  604. }
  605. if (fFoundOne && (!fCheckColorDepth || CheckMinColorDepth(hInst, dwCurMinDepth, COMBOENTRY(combos, c, s))))
  606. {
  607. if (dwSizeNum++ == dwSizeIndex)
  608. {
  609. hr = GetResString(hInst, L"SIZENAMES", s, ptn->szName, ARRAYSIZE(ptn->szName));
  610. if (FAILED(hr))
  611. *ptn->szName = 0;
  612. if (! LoadString(hInst, s+RES_BASENUM_SIZEDISPLAYS, ptn->szDisplayName, ARRAYSIZE(ptn->szDisplayName)))
  613. *ptn->szDisplayName = 0;
  614. if (! LoadString(hInst, s+RES_BASENUM_SIZETOOLTIPS, ptn->szToolTip, ARRAYSIZE(ptn->szToolTip)))
  615. *ptn->szToolTip = 0;
  616. gotall = TRUE;
  617. break;
  618. }
  619. }
  620. }
  621. if ((SUCCEEDED(hr)) && (! gotall))
  622. hr = MakeError32(ERROR_NOT_FOUND);
  623. exit:
  624. return hr;
  625. }
  626. //---------------------------------------------------------------------------
  627. HRESULT _EnumThemeColors(HINSTANCE hInst, LPCWSTR pszThemeName,
  628. OPTIONAL LPCWSTR pszSizeName, DWORD dwColorIndex, OUT THEMENAMEINFO *ptn, BOOL fCheckColorDepth)
  629. {
  630. HRESULT hr;
  631. COLORSIZECOMBOS *combos;
  632. hr = FindComboData(hInst, &combos);
  633. if (FAILED(hr))
  634. goto exit;
  635. int iMinSize, iMaxSize;
  636. iMinSize = 0;
  637. iMaxSize = combos->cSizes-1;
  638. if (pszSizeName) // translate "pszSizeName" into a size number
  639. {
  640. int index;
  641. hr = GetSizeIndex(hInst, pszSizeName, &index);
  642. if (FAILED(hr))
  643. goto exit;
  644. //---- restrict our search to just this size ----
  645. iMinSize = index;
  646. iMaxSize = index;
  647. }
  648. int s, c;
  649. DWORD dwColorNum;
  650. dwColorNum = 0;
  651. BOOL gotall;
  652. gotall = FALSE;
  653. DWORD dwCurMinDepth = 0;
  654. if (fCheckColorDepth)
  655. {
  656. dwCurMinDepth = MinimumDisplayColorDepth();
  657. }
  658. for (c=0; c < combos->cColorSchemes; c++)
  659. {
  660. BOOL fFoundOne = FALSE;
  661. for (s=iMinSize; s <= iMaxSize; s++)
  662. {
  663. if (COMBOENTRY(combos, c, s) != -1)
  664. {
  665. fFoundOne = TRUE;
  666. break;
  667. }
  668. }
  669. if (fFoundOne && (!fCheckColorDepth || CheckMinColorDepth(hInst, dwCurMinDepth, COMBOENTRY(combos, c, s))))
  670. {
  671. if (dwColorNum++ == dwColorIndex)
  672. {
  673. hr = GetResString(hInst, L"COLORNAMES", c, ptn->szName, ARRAYSIZE(ptn->szName));
  674. if (FAILED(hr))
  675. *ptn->szName = 0;
  676. if (! LoadString(hInst, c+RES_BASENUM_COLORDISPLAYS, ptn->szDisplayName, ARRAYSIZE(ptn->szDisplayName)))
  677. *ptn->szDisplayName = 0;
  678. if (! LoadString(hInst, c+RES_BASENUM_COLORTOOLTIPS, ptn->szToolTip, ARRAYSIZE(ptn->szToolTip)))
  679. *ptn->szToolTip = 0;
  680. gotall = true;
  681. break;
  682. }
  683. }
  684. }
  685. if ((SUCCEEDED(hr)) && (! gotall))
  686. hr = MakeError32(ERROR_NOT_FOUND);
  687. exit:
  688. return hr;
  689. }