Leaked source code of windows server 2003
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.

1343 lines
42 KiB

  1. /*****************************************************************************\
  2. FILE: util.cpp
  3. DESCRIPTION:
  4. Shared stuff that operates on all classes.
  5. BryanSt 4/4/2000 (Bryan Starbuck)
  6. Copyright (C) Microsoft Corp 2000-2000. All rights reserved.
  7. \*****************************************************************************/
  8. #include "priv.h"
  9. #include <atlbase.h> // USES_CONVERSION
  10. #include <errors.h> // \\themes\\inc
  11. #include <ctxdef.h> // hydra stuff
  12. #include <regapi.h> // WINSTATION_REG_NAME
  13. #include "WMPAPITemp.h"
  14. #define SECURITY_WIN32
  15. #include <sspi.h>
  16. extern "C" {
  17. #include <Secext.h> // for GetUserNameEx()
  18. }
  19. #define DECL_CRTFREE
  20. #include <crtfree.h>
  21. #include "util.h"
  22. /////////////////////////////////////////////////////////////////////
  23. // String Helpers
  24. /////////////////////////////////////////////////////////////////////
  25. HINSTANCE g_hinst; // My instance handle
  26. HANDLE g_hLogFile = INVALID_HANDLE_VALUE;
  27. #ifdef DEBUG
  28. DWORD g_TLSliStopWatchStartHi = 0xFFFFFFFF;
  29. DWORD g_TLSliStopWatchStartLo = 0xFFFFFFFF;
  30. LARGE_INTEGER g_liStopWatchFreq = {0};
  31. #endif // DEBUG
  32. /////////////////////////////////////////////////////////////////////
  33. // Debug Timing Helpers
  34. /////////////////////////////////////////////////////////////////////
  35. #ifdef DEBUG
  36. void DebugStartWatch(void)
  37. {
  38. LARGE_INTEGER liStopWatchStart;
  39. if (-1 == g_TLSliStopWatchStartHi)
  40. {
  41. g_TLSliStopWatchStartHi = TlsAlloc();
  42. g_TLSliStopWatchStartLo = TlsAlloc();
  43. liStopWatchStart.QuadPart = 0;
  44. QueryPerformanceFrequency(&g_liStopWatchFreq); // Only a one time call since it's value can't change while the system is running.
  45. }
  46. else
  47. {
  48. liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
  49. liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
  50. }
  51. AssertMsg((0 == liStopWatchStart.QuadPart), TEXT("Someone else is using our perf timer. Stop nesting.")); // If you hit this, then the stopwatch is nested.
  52. QueryPerformanceCounter(&liStopWatchStart);
  53. TlsSetValue(g_TLSliStopWatchStartHi, IntToPtr(liStopWatchStart.HighPart));
  54. TlsSetValue(g_TLSliStopWatchStartLo, IntToPtr(liStopWatchStart.LowPart));
  55. }
  56. DWORD DebugStopWatch(void)
  57. {
  58. LARGE_INTEGER liDiff;
  59. LARGE_INTEGER liStopWatchStart;
  60. QueryPerformanceCounter(&liDiff);
  61. liStopWatchStart.HighPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartHi));
  62. liStopWatchStart.LowPart = PtrToUlong(TlsGetValue(g_TLSliStopWatchStartLo));
  63. liDiff.QuadPart -= liStopWatchStart.QuadPart;
  64. ASSERT(0 != g_liStopWatchFreq.QuadPart); // I don't like to fault with div 0.
  65. DWORD dwTime = (DWORD)((liDiff.QuadPart * 1000) / g_liStopWatchFreq.QuadPart);
  66. TlsSetValue(g_TLSliStopWatchStartHi, (LPVOID) 0);
  67. TlsSetValue(g_TLSliStopWatchStartLo, (LPVOID) 0);
  68. return dwTime;
  69. }
  70. #endif // DEBUG
  71. /////////////////////////////////////////////////////////////////////
  72. // String Helpers
  73. /////////////////////////////////////////////////////////////////////
  74. HRESULT HrSysAllocStringW(IN const OLECHAR * pwzSource, OUT BSTR * pbstrDest)
  75. {
  76. HRESULT hr = S_OK;
  77. if (pbstrDest)
  78. {
  79. *pbstrDest = SysAllocString(pwzSource);
  80. if (pwzSource)
  81. {
  82. if (*pbstrDest)
  83. hr = S_OK;
  84. else
  85. hr = E_OUTOFMEMORY;
  86. }
  87. }
  88. return hr;
  89. }
  90. HRESULT HrSysAllocString(IN const OLECHAR * pwzSource, OUT BSTR * pbstrDest)
  91. {
  92. HRESULT hr = S_OK;
  93. if (pbstrDest)
  94. {
  95. *pbstrDest = SysAllocString(pwzSource);
  96. if (pwzSource)
  97. {
  98. if (*pbstrDest)
  99. hr = S_OK;
  100. else
  101. hr = E_OUTOFMEMORY;
  102. }
  103. }
  104. return hr;
  105. }
  106. /////////////////////////////////////////////////////////////////////
  107. // File System Wrapping Helpers
  108. /////////////////////////////////////////////////////////////////////
  109. HRESULT HrSHFileOpDeleteFile(HWND hwnd, FILEOP_FLAGS dwFlags, LPTSTR pszPath)
  110. {
  111. HRESULT hr = S_OK;
  112. SHFILEOPSTRUCT FileOp = {0};
  113. pszPath[lstrlen(pszPath)+1] = 0; // Ensure double terminated.
  114. FileOp.wFunc = FO_DELETE;
  115. FileOp.fAnyOperationsAborted = TRUE;
  116. FileOp.hwnd = hwnd;
  117. FileOp.pFrom = pszPath;
  118. FileOp.fFlags = dwFlags;
  119. if (SHFileOperation(&FileOp))
  120. {
  121. hr = ResultFromLastError();
  122. }
  123. return hr;
  124. }
  125. /////////////////////////////////////////////////////////////////////
  126. // Registry Helpers
  127. /////////////////////////////////////////////////////////////////////
  128. HRESULT HrRegOpenKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
  129. {
  130. DWORD dwError = RegOpenKeyEx(hKey, lpSubKey, ulOptions, samDesired, phkResult);
  131. return ResultFromWin32(dwError);
  132. }
  133. HRESULT HrRegCreateKeyEx(HKEY hKey, LPCTSTR lpSubKey, DWORD Reserved, LPTSTR lpClass, DWORD dwOptions,
  134. REGSAM samDesired, LPSECURITY_ATTRIBUTES lpSecurityAttributes, PHKEY phkResult, LPDWORD lpdwDisposition)
  135. {
  136. DWORD dwError = RegCreateKeyEx(hKey, lpSubKey, Reserved, lpClass, dwOptions, samDesired, lpSecurityAttributes, phkResult, lpdwDisposition);
  137. return ResultFromWin32(dwError);
  138. }
  139. HRESULT HrRegQueryValueEx(IN HKEY hKey, IN LPCTSTR lpValueName, IN LPDWORD lpReserved, IN LPDWORD lpType, IN LPBYTE lpData, IN LPDWORD lpcbData)
  140. {
  141. DWORD dwError = RegQueryValueEx(hKey, lpValueName, lpReserved, lpType, lpData, lpcbData);
  142. return ResultFromWin32(dwError);
  143. }
  144. HRESULT HrRegSetValueEx(IN HKEY hKey, IN LPCTSTR lpValueName, IN DWORD dwReserved, IN DWORD dwType, IN CONST BYTE *lpData, IN DWORD cbData)
  145. {
  146. DWORD dwError = RegSetValueEx(hKey, lpValueName, dwReserved, dwType, lpData, cbData);
  147. return ResultFromWin32(dwError);
  148. }
  149. HRESULT HrRegEnumValue(HKEY hKey, DWORD dwIndex, LPTSTR lpValueName, LPDWORD lpcValueName, LPDWORD lpReserved,
  150. LPDWORD lpType, LPBYTE lpData, LPDWORD lpcbData)
  151. {
  152. DWORD dwError = RegEnumValue(hKey, dwIndex, lpValueName, lpcValueName, lpReserved, lpType, lpData, lpcbData);
  153. return ResultFromWin32(dwError);
  154. }
  155. HRESULT HrRegQueryInfoKey(HKEY hKey, LPTSTR lpClass, LPDWORD lpcClass, LPDWORD lpReserved, LPDWORD lpcSubKeys, LPDWORD lpcMaxSubKeyLen,
  156. LPDWORD lpcMaxClassLen, LPDWORD lpcValues, LPDWORD lpcMaxValueNameLen, LPDWORD lpcMaxValueLen, LPDWORD lpcbSecurityDescriptor, PFILETIME lpftLastWriteTime)
  157. {
  158. DWORD dwError = RegQueryInfoKey(hKey, lpClass, lpcClass, lpReserved, lpcSubKeys, lpcMaxSubKeyLen,
  159. lpcMaxClassLen, lpcValues, lpcMaxValueNameLen, lpcMaxValueLen, lpcbSecurityDescriptor, lpftLastWriteTime);
  160. return ResultFromWin32(dwError);
  161. }
  162. HRESULT HrBStrRegQueryValue(IN HKEY hKey, IN LPCTSTR lpValueName, OUT BSTR * pbstr)
  163. {
  164. TCHAR szValue[MAX_PATH];
  165. DWORD dwType;
  166. DWORD cbSize = sizeof(szValue);
  167. HRESULT hr = HrRegQueryValueEx(hKey, lpValueName, 0, &dwType, (BYTE *)szValue, &cbSize);
  168. *pbstr = NULL;
  169. if (SUCCEEDED(hr))
  170. {
  171. hr = HrSysAllocStringW(szValue, pbstr);
  172. }
  173. return hr;
  174. }
  175. HRESULT HrSHGetValue(IN HKEY hKey, IN LPCTSTR pszSubKey, OPTIONAL IN LPCTSTR pszValue, OPTIONAL OUT LPDWORD pdwType,
  176. OPTIONAL OUT LPVOID pvData, OPTIONAL OUT LPDWORD pcbData)
  177. {
  178. DWORD dwError = SHGetValue(hKey, pszSubKey, pszValue, pdwType, pvData, pcbData);
  179. return ResultFromWin32(dwError);
  180. }
  181. HRESULT HrSHSetValue(IN HKEY hkey, IN LPCTSTR pszSubKey, OPTIONAL IN LPCTSTR pszValue, DWORD dwType, OPTIONAL OUT LPVOID pvData, IN DWORD cbData)
  182. {
  183. DWORD dwError = SHSetValue(hkey, pszSubKey, pszValue, dwType, pvData, cbData);
  184. return ResultFromWin32(dwError);
  185. }
  186. HRESULT HrRegSetValueString(IN HKEY hKey, IN LPCTSTR pszSubKey, IN LPCTSTR pszValueName, OUT LPCWSTR pszString)
  187. {
  188. DWORD cbSize = ((lstrlenW(pszString) + 1) * sizeof(pszString[0]));
  189. return HrSHSetValue(hKey, pszSubKey, pszValueName, REG_SZ, (BYTE *)pszString, cbSize);
  190. }
  191. HRESULT HrRegGetValueString(IN HKEY hKey, IN LPCTSTR pszSubKey, IN LPCTSTR pszValueName, IN LPWSTR pszString, IN DWORD cchSize)
  192. {
  193. DWORD dwType;
  194. DWORD cbSize = (cchSize * sizeof(pszString[0]));
  195. HRESULT hr = HrSHGetValue(hKey, pszSubKey, pszValueName, &dwType, (BYTE *)pszString, &cbSize);
  196. if (SUCCEEDED(hr) && (REG_SZ != dwType))
  197. {
  198. hr = E_FAIL;
  199. }
  200. return hr;
  201. }
  202. /*****************************************************************************\
  203. DESCRIPTION:
  204. This function will store paths in the registry. The user calls the
  205. fuction with full paths are they are converted to relative path. The
  206. strings prefer to be stored in REG_EXPAND_SZ, but it will fallback to
  207. REG_SZ if needed.
  208. \*****************************************************************************/
  209. HRESULT HrRegSetPath(IN HKEY hKey, IN LPCTSTR pszSubKey, IN LPCTSTR pszValueName, BOOL fUseExpandSZ, OUT LPCWSTR pszPath)
  210. {
  211. TCHAR szFinalPath[MAX_PATH];
  212. if (!PathUnExpandEnvStrings(pszPath, szFinalPath, ARRAYSIZE(szFinalPath)))
  213. {
  214. StringCchCopy(szFinalPath, ARRAYSIZE(szFinalPath), pszPath); // We failed so use the original.
  215. }
  216. DWORD cbSize = ((lstrlenW(szFinalPath) + 1) * sizeof(szFinalPath[0]));
  217. HRESULT hr = E_FAIL;
  218. if (fUseExpandSZ)
  219. {
  220. hr = HrSHSetValue(hKey, pszSubKey, pszValueName, REG_EXPAND_SZ, (BYTE *)szFinalPath, cbSize);
  221. }
  222. if (FAILED(hr))
  223. {
  224. // Maybe it already exists as a REG_SZ so we will store it there. Note that we are still storing it
  225. // unexpanded even thought it's in REG_SZ. If the caller does not like it, use
  226. // another function like SHRegSetPath().
  227. cbSize = ((lstrlenW(szFinalPath) + 1) * sizeof(szFinalPath[0]));
  228. hr = HrSHSetValue(hKey, pszSubKey, pszValueName, REG_SZ, (BYTE *)szFinalPath, cbSize);
  229. }
  230. return hr;
  231. }
  232. HRESULT HrRegGetPath(IN HKEY hKey, IN LPCTSTR pszSubKey, IN LPCTSTR pszValueName, IN LPWSTR pszPath, IN DWORD cchSize)
  233. {
  234. TCHAR szFinalPath[MAX_PATH];
  235. DWORD dwType;
  236. DWORD cbSize = sizeof(szFinalPath);
  237. HRESULT hr = HrSHGetValue(hKey, pszSubKey, pszValueName, &dwType, (BYTE *)szFinalPath, &cbSize);
  238. if (SUCCEEDED(hr) &&
  239. ((REG_EXPAND_SZ == dwType) || (REG_SZ == dwType)))
  240. {
  241. if (0 == SHExpandEnvironmentStrings(szFinalPath, pszPath, cchSize))
  242. {
  243. StringCchCopy(pszPath, cchSize, szFinalPath); // We failed so use the original.
  244. }
  245. }
  246. return hr;
  247. }
  248. HRESULT HrRegDeleteValue(IN HKEY hKey, IN LPCTSTR pszSubKey, IN LPCTSTR pszValueName)
  249. {
  250. HRESULT hr = S_OK;
  251. HKEY hKeySub = hKey;
  252. if (pszSubKey)
  253. {
  254. hr = HrRegOpenKeyEx(hKey, pszSubKey, 0, KEY_WRITE, &hKeySub);
  255. }
  256. if (SUCCEEDED(hr))
  257. {
  258. DWORD dwError = RegDeleteValue(hKeySub, pszValueName);
  259. hr = ResultFromWin32(dwError);
  260. }
  261. if (hKeySub == hKey)
  262. {
  263. RegCloseKey(hKeySub);
  264. }
  265. return hr;
  266. }
  267. DWORD HrRegGetDWORD(HKEY hKey, LPCWSTR szKey, LPCWSTR szValue, DWORD dwDefault)
  268. {
  269. DWORD dwResult = dwDefault;
  270. DWORD cbSize = sizeof(dwResult);
  271. DWORD dwType;
  272. DWORD dwError = SHGetValue(hKey, szKey, szValue, &dwType, &dwResult, &cbSize);
  273. if ((ERROR_SUCCESS != dwError) ||
  274. ((REG_DWORD != dwType) && (REG_BINARY != dwType)) || (sizeof(dwResult) != cbSize))
  275. {
  276. return dwDefault;
  277. }
  278. return dwResult;
  279. }
  280. HRESULT HrRegSetDWORD(HKEY hKey, LPCWSTR szKey, LPCWSTR szValue, DWORD dwData)
  281. {
  282. DWORD dwError = SHSetValue(hKey, szKey, szValue, REG_DWORD, &dwData, sizeof(dwData));
  283. return ResultFromWin32(dwError);
  284. }
  285. /////////////////////////////////////////////////////////////////////
  286. // Palette Helpers
  287. /////////////////////////////////////////////////////////////////////
  288. COLORREF GetNearestPaletteColor(HPALETTE hpal, COLORREF rgb)
  289. {
  290. PALETTEENTRY pe = {0};
  291. UINT nIndex = GetNearestPaletteIndex(hpal, rgb & 0x00FFFFFF);
  292. if (CLR_INVALID != nIndex)
  293. {
  294. GetPaletteEntries(hpal, nIndex, 1, &pe);
  295. }
  296. return RGB(pe.peRed, pe.peGreen, pe.peBlue);
  297. }
  298. BOOL IsPaletteColor(HPALETTE hpal, COLORREF rgb)
  299. {
  300. return GetNearestPaletteColor(hpal, rgb) == (rgb & 0xFFFFFF);
  301. }
  302. BOOL _InitComCtl32()
  303. {
  304. static BOOL fInitialized = FALSE;
  305. if (!fInitialized)
  306. {
  307. INITCOMMONCONTROLSEX icc;
  308. icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
  309. icc.dwICC = (ICC_ANIMATE_CLASS | ICC_USEREX_CLASSES | ICC_COOL_CLASSES | ICC_INTERNET_CLASSES | ICC_PAGESCROLLER_CLASS | ICC_NATIVEFNTCTL_CLASS | ICC_LISTVIEW_CLASSES | ICC_LINK_CLASS);
  310. fInitialized = InitCommonControlsEx(&icc);
  311. }
  312. return fInitialized;
  313. }
  314. DWORD GetCurrentSessionID(void)
  315. {
  316. DWORD dwProcessID = (DWORD) -1;
  317. ProcessIdToSessionId(GetCurrentProcessId(), &dwProcessID);
  318. return dwProcessID;
  319. }
  320. typedef struct
  321. {
  322. LPCWSTR pszRegKey;
  323. LPCWSTR pszRegValue;
  324. } TSPERFFLAG_ITEM;
  325. const TSPERFFLAG_ITEM s_TSPerfFlagItems[] =
  326. {
  327. {L"Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Remote\\%d", L"ActiveDesktop"}, // TSPerFlag_NoADWallpaper
  328. {L"Remote\\%d\\Control Panel\\Desktop", L"Wallpaper"}, // TSPerFlag_NoWallpaper
  329. {L"Software\\Microsoft\\Windows\\CurrentVersion\\ThemeManager\\Remote\\%d", L"ThemeActive"}, // TSPerFlag_NoVisualStyles
  330. {L"Remote\\%d\\Control Panel\\Desktop", L"DragFullWindows"}, // TSPerFlag_NoWindowDrag
  331. {L"Remote\\%d\\Control Panel\\Desktop", L"SmoothScroll"}, // TSPerFlag_NoAnimation
  332. };
  333. BOOL IsTSPerfFlagEnabled(enumTSPerfFlag eTSFlag)
  334. {
  335. BOOL fIsTSFlagEnabled = FALSE;
  336. static BOOL s_fTSSession = -10;
  337. if (-10 == s_fTSSession)
  338. {
  339. s_fTSSession = GetSystemMetrics(SM_REMOTESESSION);
  340. }
  341. if (s_fTSSession)
  342. {
  343. TCHAR szTemp[MAX_PATH];
  344. DWORD dwType;
  345. DWORD cbSize = sizeof(szTemp);
  346. TCHAR szRegKey[MAX_PATH];
  347. StringCchPrintf(szRegKey, ARRAYSIZE(szRegKey), s_TSPerfFlagItems[eTSFlag].pszRegKey, GetCurrentSessionID());
  348. if (ERROR_SUCCESS == SHGetValueW(HKEY_CURRENT_USER, szRegKey, s_TSPerfFlagItems[eTSFlag].pszRegValue, &dwType, (void *)szTemp, &cbSize))
  349. {
  350. fIsTSFlagEnabled = TRUE;
  351. }
  352. }
  353. return fIsTSFlagEnabled;
  354. }
  355. HRESULT HrShellExecute(HWND hwnd, LPCTSTR lpVerb, LPCTSTR lpFile, LPCTSTR lpParameters, LPCTSTR lpDirectory, INT nShowCmd)
  356. {
  357. HRESULT hr = S_OK;
  358. HINSTANCE hReturn = ShellExecute(hwnd, lpVerb, lpFile, lpParameters, lpDirectory, nShowCmd);
  359. if ((HINSTANCE)32 > hReturn)
  360. {
  361. hr = ResultFromLastError();
  362. }
  363. return hr;
  364. }
  365. HRESULT StrReplaceToken(IN LPCTSTR pszToken, IN LPCTSTR pszReplaceValue, IN LPTSTR pszString, IN DWORD cchSize)
  366. {
  367. HRESULT hr = S_OK;
  368. LPTSTR pszTempLastHalf = NULL;
  369. LPTSTR pszNextToken = pszString;
  370. while (0 != (pszNextToken = StrStrI(pszNextToken, pszToken)))
  371. {
  372. // We found one.
  373. LPTSTR pszPastToken = pszNextToken + lstrlen(pszToken);
  374. Str_SetPtr(&pszTempLastHalf, pszPastToken); // Keep a copy because we will overwrite it.
  375. pszNextToken[0] = 0; // Remove the rest of the string.
  376. StringCchCat(pszString, cchSize, pszReplaceValue);
  377. StringCchCat(pszString, cchSize, pszTempLastHalf);
  378. pszNextToken += lstrlen(pszReplaceValue);
  379. }
  380. Str_SetPtr(&pszTempLastHalf, NULL);
  381. return hr;
  382. }
  383. HRESULT HrWritePrivateProfileStringW(LPCWSTR pszAppName, LPCWSTR pszKeyName, LPCWSTR pszString, LPCWSTR pszFileName)
  384. {
  385. HRESULT hr = S_OK;
  386. if (!WritePrivateProfileStringW(pszAppName, pszKeyName, pszString, pszFileName))
  387. {
  388. hr = ResultFromLastError();
  389. }
  390. return hr;
  391. }
  392. BOOL IUnknown_CompareCLSID(IN IUnknown * punk, IN CLSID clsid)
  393. {
  394. BOOL fIsEqual = FALSE;
  395. if (punk)
  396. {
  397. CLSID clsidPageID;
  398. HRESULT hr = IUnknown_GetClassID(punk, &clsidPageID);
  399. if (SUCCEEDED(hr) && IsEqualCLSID(clsidPageID, clsid))
  400. {
  401. fIsEqual = TRUE;
  402. }
  403. }
  404. return fIsEqual;
  405. }
  406. HRESULT IEnumUnknown_FindCLSID(IN IUnknown * punk, IN CLSID clsid, OUT IUnknown ** ppunkFound)
  407. {
  408. HRESULT hr = E_INVALIDARG;
  409. if (punk && ppunkFound)
  410. {
  411. IEnumUnknown * pEnum;
  412. *ppunkFound = NULL;
  413. hr = punk->QueryInterface(IID_PPV_ARG(IEnumUnknown, &pEnum));
  414. if (SUCCEEDED(hr))
  415. {
  416. IUnknown * punkToTry;
  417. ULONG ulFetched;
  418. pEnum->Reset();
  419. hr = E_FAIL;
  420. while (SUCCEEDED(pEnum->Next(1, &punkToTry, &ulFetched)) &&
  421. (1 == ulFetched))
  422. {
  423. if (IUnknown_CompareCLSID(punkToTry, clsid))
  424. {
  425. *ppunkFound = punkToTry;
  426. hr = S_OK;
  427. break;
  428. }
  429. punkToTry->Release();
  430. }
  431. pEnum->Release();
  432. }
  433. }
  434. return hr;
  435. }
  436. BYTE WINAPI MyStrToByte(LPCTSTR sz)
  437. {
  438. BYTE l=0;
  439. while (*sz >= TEXT('0') && *sz <= TEXT('9'))
  440. {
  441. l = (BYTE) l*10 + (*sz++ - TEXT('0'));
  442. }
  443. return l;
  444. }
  445. COLORREF ConvertColor(LPTSTR pszColor)
  446. {
  447. BYTE RGBTemp[3];
  448. LPTSTR pszTemp = pszColor;
  449. UINT i;
  450. if (!pszColor || !*pszColor)
  451. {
  452. return RGB(0,0,0);
  453. }
  454. for (i =0; i < 3; i++)
  455. {
  456. // Remove leading spaces
  457. while (*pszTemp == TEXT(' '))
  458. {
  459. pszTemp++;
  460. }
  461. // Set pszColor to the beginning of the number
  462. pszColor = pszTemp;
  463. // Find the end of the number and null terminate
  464. while ((*pszTemp) && (*pszTemp != TEXT(' ')))
  465. {
  466. pszTemp++;
  467. }
  468. if (*pszTemp != TEXT('\0'))
  469. {
  470. *pszTemp = TEXT('\0');
  471. }
  472. pszTemp++;
  473. RGBTemp[i] = MyStrToByte(pszColor);
  474. }
  475. return (RGB(RGBTemp[0], RGBTemp[1], RGBTemp[2]));
  476. }
  477. // Paremeters:
  478. // hwndOwner -- owner window
  479. // idTemplate -- specifies template (e.g., "Can't open %2%s\n\n%1%s")
  480. // hr -- specifies the HRESULT error code
  481. // pszParam -- specifies the 2nd parameter to idTemplate
  482. // dwFlags -- flags for MessageBox
  483. UINT ErrorMessageBox(HWND hwndOwner, LPCTSTR pszTitle, UINT idTemplate, HRESULT hr, LPCTSTR pszParam, UINT dwFlags)
  484. {
  485. TCHAR szErrNumString[MAX_PATH * 2];
  486. TCHAR szTemplate[MAX_PATH * 2];
  487. TCHAR szErrMsg[MAX_PATH * 2];
  488. if (!FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, hr, 0, szErrNumString, ARRAYSIZE(szErrNumString), NULL))
  489. {
  490. szErrNumString[0] = 0; // We will not be able to display an error message.
  491. }
  492. // These error messages are so useless to customers, that we prefer to leave it blank.
  493. if ((E_INVALIDARG == hr) ||
  494. (ResultFromWin32(ERROR_INVALID_PARAMETER) == hr))
  495. {
  496. szErrNumString[0] = 0;
  497. }
  498. LoadString(HINST_THISDLL, idTemplate, szTemplate, ARRAYSIZE(szTemplate));
  499. if (pszParam)
  500. {
  501. StringCchPrintf(szErrMsg, ARRAYSIZE(szErrMsg), szTemplate, szErrNumString, pszParam);
  502. }
  503. else
  504. {
  505. StringCchPrintf(szErrMsg, ARRAYSIZE(szErrMsg), szTemplate, szErrNumString);
  506. }
  507. return MessageBox(hwndOwner, szErrMsg, pszTitle, (MB_OK | MB_ICONERROR));
  508. }
  509. HRESULT DisplayThemeErrorDialog(HWND hwndParent, HRESULT hrError, UINT nTitle, UINT nTemplate)
  510. {
  511. HRESULT hr = S_OK;
  512. if (FAILED(hrError))
  513. {
  514. hr = ResultFromWin32(ERROR_CANCELLED);
  515. if (!g_fInSetup && // Don't display an error during setup.
  516. (ResultFromWin32(ERROR_CANCELLED) != hrError))
  517. {
  518. //---- get error from theme manager ----
  519. WCHAR szErrorMsg[MAX_PATH*2];
  520. WCHAR szTitle[MAX_PATH];
  521. szErrorMsg[0] = 0; // In case the error function fails.
  522. if (FAILED(hrError))
  523. {
  524. PARSE_ERROR_INFO Info = {sizeof(Info)};
  525. if (SUCCEEDED(GetThemeParseErrorInfo(&Info)))
  526. {
  527. StringCchCopy(szErrorMsg, ARRAYSIZE(szErrorMsg), Info.szMsg);
  528. }
  529. else
  530. {
  531. *szErrorMsg = 0; // no error avail
  532. }
  533. }
  534. // We want to display UI if an error occured here. We want to do
  535. // it instead of our parent because THEMELOADPARAMS contains
  536. // extra error information that we can't pass back to the caller.
  537. // However, we will only display error UI if our caller wants us
  538. // to. We determine that by the fact that they make an hwnd available
  539. // to us. We get the hwnd by getting our site pointer and getting
  540. // the hwnd via ::GetWindow().
  541. LoadString(HINST_THISDLL, nTitle, szTitle, ARRAYSIZE(szTitle));
  542. ErrorMessageBox(hwndParent, szTitle, nTemplate, hrError, szErrorMsg, (MB_OK | MB_ICONEXCLAMATION));
  543. }
  544. }
  545. return hr;
  546. }
  547. extern BOOL FadeEffectAvailable(void);
  548. void LogStartInformation(void)
  549. {
  550. BOOL fTemp;
  551. // Frequently users will report that something is broken in the Display CPL.
  552. // However, the real problem is that someone turned on a policy that locks UI
  553. // and the user didn't know that the policy was enabled. We log those here so
  554. // it's quick to find those issues.
  555. if (SHRestricted(REST_NODISPLAYCPL)) LogStatus("POLICY ENABLED: Do not show the Display CPL.");
  556. if (SHRestricted(REST_NODISPLAYAPPEARANCEPAGE)) LogStatus("POLICY ENABLED: Hide the Themes and Appearance tab.");
  557. if (SHRestricted(REST_NOTHEMESTAB)) LogStatus("POLICY ENABLED: Hide the Themes tab.");
  558. if (SHRestricted(REST_NODISPBACKGROUND)) LogStatus("POLICY ENABLED: Hide the Desktop tab.");
  559. if (SHRestricted(REST_NODISPSCREENSAVEPG)) LogStatus("POLICY ENABLED: Hide the ScreenSaver tab.");
  560. if (SHRestricted(REST_NODISPSETTINGSPG)) LogStatus("POLICY ENABLED: Hide the Settings tab.");
  561. if (SHRestricted(REST_NOVISUALSTYLECHOICE)) LogStatus("POLICY ENABLED: User not allowed to change the Visual Style.");
  562. if (SHRestricted(REST_NOCOLORCHOICE)) LogStatus("POLICY ENABLED: User Not allowed to change the Visual Style Color Selection.");
  563. if (SHRestricted(REST_NOSIZECHOICE)) LogStatus("POLICY ENABLED: User not allowed to change the Visual Style size selection.");
  564. if (0 != SHGetRestriction(NULL,POLICY_KEY_EXPLORER,POLICY_VALUE_ANIMATION)) LogStatus("POLICY ENABLED: Policy disallows fade effect. (Effects dialog)");
  565. if (0 != SHGetRestriction(NULL,POLICY_KEY_EXPLORER, POLICY_VALUE_KEYBOARDNAV)) LogStatus("POLICY ENABLED: Policy disallows changing underline key accell. (Effects dialog)");
  566. if (0 != SHGetRestriction(NULL,POLICY_KEY_ACTIVEDESKTOP, SZ_POLICY_NOCHANGEWALLPAPER)) LogStatus("POLICY ENABLED: Policy disallows changing wallpaper. (Desktop tab)");
  567. if (0 != SHGetRestriction(NULL,POLICY_KEY_SYSTEM, SZ_POLICY_NODISPSCREENSAVERPG)) LogStatus("POLICY ENABLED: Policy hides ScreenSaver page.");
  568. if (0 != SHGetRestriction(SZ_REGKEY_POLICIES_DESKTOP, NULL, SZ_POLICY_SCREENSAVEACTIVE)) LogStatus("POLICY ENABLED: Policy forces screensaver on or off");
  569. if (0 != SHGetRestriction(NULL,POLICY_KEY_EXPLORER, POLICY_VALUE_KEYBOARDNAV)) LogStatus("POLICY ENABLED: Policy disallows changing underline key accell. (Effects dialog)");
  570. if (IsTSPerfFlagEnabled(TSPerFlag_NoAnimation)) LogStatus("POLICY ENABLED: TS Perf Policy disallows animations. (Effects dialog)");
  571. if (IsTSPerfFlagEnabled(TSPerFlag_NoWindowDrag)) LogStatus("POLICY ENABLED: TS Perf Policy disallows full window drag. (Effects dialog)");
  572. if (IsTSPerfFlagEnabled(TSPerFlag_NoVisualStyles)) LogStatus("POLICY ENABLED: TS Perf Policy disallows visual styles.");
  573. if (IsTSPerfFlagEnabled(TSPerFlag_NoWallpaper)) LogStatus("POLICY ENABLED: TS Perf Policy disallows Wallpaper.");
  574. if (IsTSPerfFlagEnabled(TSPerFlag_NoADWallpaper)) LogStatus("POLICY ENABLED: TS Perf Policy disallows AD Wallpaper.");
  575. if (!FadeEffectAvailable()) LogStatus("POLICY ENABLED: A policy forces Fade Effects off (Effects dialog)");
  576. if (!ClassicSystemParametersInfo(SPI_GETFONTSMOOTHINGTYPE, 0, (PVOID)&fTemp, 0)) LogStatus("POLICY ENABLED: SPI_GETFONTSMOOTHINGTYPE hides FontSmoothing. (Effects dialog)");
  577. if (ClassicSystemParametersInfo(SPI_GETUIEFFECTS, 0, (PVOID) &fTemp, 0) && !fTemp) LogStatus("POLICY ENABLED: SPI_GETUIEFFECTS hides lots of UI effects. (Effects dialog)");
  578. if (ClassicSystemParametersInfo(SPI_GETGRADIENTCAPTIONS, 0, (PVOID) &fTemp, 0) && !fTemp) LogStatus("POLICY ENABLED: SPI_GETGRADIENTCAPTIONS turns off Caption bar Gradients. (Advance Appearance)");
  579. }
  580. void LogStatus(LPCSTR pszMessage, ...)
  581. {
  582. static int nLogOn = -1;
  583. va_list vaParamList;
  584. va_start(vaParamList, pszMessage);
  585. if (-1 == nLogOn)
  586. {
  587. nLogOn = (SHRegGetBoolUSValue(SZ_THEMES, SZ_REGVALUE_LOGINFO, FALSE, FALSE) ? 1 : 0);
  588. }
  589. if (1 == nLogOn)
  590. {
  591. if (INVALID_HANDLE_VALUE == g_hLogFile)
  592. {
  593. TCHAR szPath[MAX_PATH];
  594. if (GetWindowsDirectory(szPath, ARRAYSIZE(szPath)))
  595. {
  596. if (PathAppend(szPath, TEXT("Theme.log")))
  597. {
  598. g_hLogFile = CreateFile(szPath, (GENERIC_READ | GENERIC_WRITE), FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  599. if (INVALID_HANDLE_VALUE != g_hLogFile)
  600. {
  601. WCHAR szUserName[MAX_PATH];
  602. CHAR szTimeDate[MAX_PATH];
  603. CHAR szHeader[MAX_PATH];
  604. FILETIME ftCurrentUTC;
  605. FILETIME ftCurrent;
  606. SYSTEMTIME stCurrent;
  607. DWORD cbWritten;
  608. SetFilePointer(g_hLogFile, 0, NULL, FILE_END);
  609. GetLocalTime(&stCurrent);
  610. SystemTimeToFileTime(&stCurrent, &ftCurrent);
  611. LocalFileTimeToFileTime(&ftCurrent, &ftCurrentUTC);
  612. SHFormatDateTimeA(&ftCurrentUTC, NULL, szTimeDate, ARRAYSIZE(szTimeDate));
  613. ULONG cchUserSize = ARRAYSIZE(szUserName);
  614. if (!GetUserNameEx(NameDisplay, szUserName, &cchUserSize) &&
  615. !GetUserNameEx(NameUserPrincipal, szUserName, &cchUserSize) &&
  616. !GetUserNameEx(NameSamCompatible, szUserName, &cchUserSize) &&
  617. !GetUserNameEx(NameUniqueId, szUserName, &cchUserSize))
  618. {
  619. szUserName[0] = 0;
  620. }
  621. TCHAR szProcess[MAX_PATH];
  622. if (!GetModuleFileName(NULL, szProcess, ARRAYSIZE(szProcess)))
  623. {
  624. szProcess[0] = 0;
  625. }
  626. StringCchPrintfA(szHeader, ARRAYSIZE(szHeader), "\r\n\r\n%hs - USER: %ls (%ls)\r\n", szTimeDate, szUserName, szProcess);
  627. WriteFile(g_hLogFile, szHeader, lstrlenA(szHeader), &cbWritten, NULL);
  628. // Log information that we need to do on every startup. (Like Policies that are on that confuse people)
  629. LogStartInformation();
  630. }
  631. }
  632. }
  633. }
  634. if (INVALID_HANDLE_VALUE != g_hLogFile)
  635. {
  636. CHAR szMessage[4000];
  637. DWORD cbWritten;
  638. StringCchVPrintfA(szMessage, ARRAYSIZE(szMessage), pszMessage, vaParamList);
  639. WriteFile(g_hLogFile, szMessage, lstrlenA(szMessage), &cbWritten, NULL);
  640. }
  641. }
  642. va_end(vaParamList);
  643. }
  644. void LogSystemMetrics(LPCSTR pszMessage, SYSTEMMETRICSALL * pSystemMetrics)
  645. {
  646. CHAR szSysMetrics[1024]; // Random because it's big.
  647. if (pSystemMetrics)
  648. {
  649. StringCchPrintfA(szSysMetrics, ARRAYSIZE(szSysMetrics), "Sz(Brdr=%d, Scrl=%d, Cap=%d, Menu=%d, Icon=%d, DXIn=%d) Ft(Cap=%d(%d), SmCap=%d(%d), Menu=%d(%d), Stus=%d(%d), Msg=%d(%d))",
  650. pSystemMetrics->schemeData.ncm.iBorderWidth,
  651. pSystemMetrics->schemeData.ncm.iScrollWidth,
  652. pSystemMetrics->schemeData.ncm.iCaptionHeight,
  653. pSystemMetrics->schemeData.ncm.iMenuHeight,
  654. pSystemMetrics->nIcon,
  655. pSystemMetrics->nDYIcon,
  656. pSystemMetrics->schemeData.ncm.lfCaptionFont.lfHeight,
  657. pSystemMetrics->schemeData.ncm.lfCaptionFont.lfCharSet,
  658. pSystemMetrics->schemeData.ncm.lfSmCaptionFont.lfHeight,
  659. pSystemMetrics->schemeData.ncm.lfSmCaptionFont.lfCharSet,
  660. pSystemMetrics->schemeData.ncm.lfMenuFont.lfHeight,
  661. pSystemMetrics->schemeData.ncm.lfMenuFont.lfCharSet,
  662. pSystemMetrics->schemeData.ncm.lfStatusFont.lfHeight,
  663. pSystemMetrics->schemeData.ncm.lfStatusFont.lfCharSet,
  664. pSystemMetrics->schemeData.ncm.lfMessageFont.lfHeight,
  665. pSystemMetrics->schemeData.ncm.lfMessageFont.lfCharSet);
  666. }
  667. else
  668. {
  669. szSysMetrics[0] = 0;
  670. }
  671. LogStatus("SYSMET: %s: %s\r\n", pszMessage, szSysMetrics);
  672. }
  673. HRESULT SHGetResourcePath(BOOL fLocaleNode, IN LPWSTR pszPath, IN DWORD cchSize)
  674. {
  675. DWORD dwFlags = (CSIDL_FLAG_CREATE | CSIDL_RESOURCES);
  676. return SHGetFolderPath(NULL, dwFlags, NULL, 0, pszPath);
  677. }
  678. #define SZ_RESOURCEDIR_TOKEN TEXT("%ResourceDir%")
  679. #define SZ_RESOURCELDIR_TOKEN TEXT("%ResourceDirL%")
  680. HRESULT ExpandResourceDir(IN LPWSTR pszPath, IN DWORD cchSize)
  681. {
  682. HRESULT hr = S_OK;
  683. BOOL fLocalized = FALSE;
  684. LPCTSTR pszToken = StrStrW(pszPath, SZ_RESOURCEDIR_TOKEN);
  685. if (!pszToken)
  686. {
  687. pszToken = StrStrW(pszPath, SZ_RESOURCELDIR_TOKEN);
  688. }
  689. // Do we have stuff to replace?
  690. if (pszToken)
  691. {
  692. // Yes, so get the replacement value.
  693. WCHAR szResourceDir[MAX_PATH];
  694. hr = SHGetResourcePath(fLocalized, szResourceDir, ARRAYSIZE(szResourceDir));
  695. if (SUCCEEDED(hr))
  696. {
  697. hr = StrReplaceToken((fLocalized ? SZ_RESOURCELDIR_TOKEN : SZ_RESOURCEDIR_TOKEN), szResourceDir, pszPath, cchSize);
  698. }
  699. }
  700. return hr;
  701. }
  702. STDAPI SHPropertyBag_WritePunk(IN IPropertyBag * pPropertyPage, IN LPCWSTR pwzPropName, IN IUnknown * punk)
  703. {
  704. HRESULT hr = E_INVALIDARG;
  705. if (pPropertyPage && pwzPropName)
  706. {
  707. VARIANT va;
  708. va.vt = VT_UNKNOWN;
  709. va.punkVal = punk;
  710. hr = pPropertyPage->Write(pwzPropName, &va);
  711. }
  712. return hr;
  713. }
  714. STDAPI SHPropertyBag_ReadByRef(IN IPropertyBag * pPropertyPage, IN LPCWSTR pwzPropName, IN void * p, IN SIZE_T cbSize)
  715. {
  716. HRESULT hr = E_INVALIDARG;
  717. if (pPropertyPage && pwzPropName && p)
  718. {
  719. VARIANT va;
  720. hr = pPropertyPage->Read(pwzPropName, &va, NULL);
  721. if (SUCCEEDED(hr))
  722. {
  723. if ((VT_BYREF == va.vt) && va.byref)
  724. {
  725. CopyMemory(p, va.byref, cbSize);
  726. }
  727. else
  728. {
  729. hr = E_FAIL;
  730. }
  731. }
  732. }
  733. return hr;
  734. }
  735. STDAPI SHPropertyBag_WriteByRef(IN IPropertyBag * pPropertyPage, IN LPCWSTR pwzPropName, IN void * p)
  736. {
  737. HRESULT hr = E_INVALIDARG;
  738. if (pPropertyPage && pwzPropName && p)
  739. {
  740. VARIANT va;
  741. va.vt = VT_BYREF;
  742. va.byref = p;
  743. hr = pPropertyPage->Write(pwzPropName, &va);
  744. }
  745. return hr;
  746. }
  747. LONG s_cSpiDummy = -1;
  748. LONG *g_pcSpiThreads = &s_cSpiDummy;
  749. void SPISetThreadCounter(LONG *pcThreads)
  750. {
  751. if (!pcThreads)
  752. pcThreads = &s_cSpiDummy;
  753. InterlockedExchangePointer((void **) &g_pcSpiThreads, pcThreads);
  754. }
  755. typedef struct
  756. {
  757. LPTHREAD_START_ROUTINE pfnThreadProc;
  758. void *pvData;
  759. UINT idThread;
  760. }SPITHREAD;
  761. DWORD CALLBACK _SPIWrapperThreadProc(void *pv)
  762. {
  763. SPITHREAD *pspi = (SPITHREAD *)pv;
  764. DWORD dwRet = pspi->pfnThreadProc(pspi->pvData);
  765. // then we check to see
  766. ASSERT( 0 != *g_pcSpiThreads );
  767. if (0 == InterlockedDecrement(g_pcSpiThreads))
  768. {
  769. PostThreadMessage(pspi->idThread, WM_NULL, 0, 0);
  770. }
  771. delete pspi;
  772. return dwRet;
  773. }
  774. BOOL SPICreateThread(LPTHREAD_START_ROUTINE pfnThreadProc, void *pvData)
  775. {
  776. SPITHREAD *pspi = new SPITHREAD;
  777. if (pspi)
  778. {
  779. pspi->idThread = GetCurrentThreadId();
  780. pspi->pfnThreadProc = pfnThreadProc;
  781. pspi->pvData = pvData;
  782. InterlockedIncrement(g_pcSpiThreads);
  783. return SHCreateThread(_SPIWrapperThreadProc, pspi, (CTF_COINIT | CTF_INSIST | CTF_FREELIBANDEXIT), NULL);
  784. }
  785. else
  786. {
  787. // CTF_INSIST
  788. pfnThreadProc(pvData);
  789. return TRUE;
  790. }
  791. }
  792. void PostMessageBroadAsync(IN UINT Msg, IN WPARAM wParam, IN LPARAM lParam)
  793. {
  794. // We don't want to hang our UI if other apps are hung or slow when
  795. // we need to tell them to update their changes. So we choose this
  796. // mechanism.
  797. //
  798. // The alternatives are:
  799. // SendMessageCallback: Except we don't need to do anything when the apps
  800. // are done.
  801. // SendMessageTimeout: Except we don't want to incure any timeout.
  802. PostMessage(HWND_BROADCAST, Msg, wParam, lParam);
  803. }
  804. typedef struct
  805. {
  806. BOOL fFree; // Do you need to call LocalFree() on pvData?
  807. UINT uiAction;
  808. UINT uiParam;
  809. UINT fWinIni;
  810. void * pvData;
  811. CDimmedWindow* pDimmedWindow;
  812. } SPIS_INFO;
  813. DWORD SystemParametersInfoAsync_WorkerThread(IN void *pv)
  814. {
  815. SPIS_INFO * pSpisInfo = (SPIS_INFO *) pv;
  816. HINSTANCE hInstance = LoadLibrary(TEXT("desk.cpl"));
  817. if (pSpisInfo)
  818. {
  819. ClassicSystemParametersInfo(pSpisInfo->uiAction, pSpisInfo->uiParam, pSpisInfo->pvData, pSpisInfo->fWinIni);
  820. if (pSpisInfo->fFree && pSpisInfo->pvData)
  821. {
  822. LocalFree(pSpisInfo->pvData);
  823. }
  824. if (pSpisInfo->pDimmedWindow)
  825. {
  826. pSpisInfo->pDimmedWindow->Release();
  827. }
  828. LocalFree(pv);
  829. }
  830. if (hInstance)
  831. {
  832. FreeLibrary(hInstance);
  833. }
  834. return 0;
  835. }
  836. void SystemParametersInfoAsync(IN UINT uiAction, IN UINT uiParam, IN void * pvParam, IN DWORD cbSize, IN UINT fWinIni, IN CDimmedWindow* pDimmedWindow)
  837. {
  838. // ClassicSystemParametersInfo() will hang if a top level window is hung (#162570) and USER will not fix that bug.
  839. // Therefore, we need to make that API call on a background thread because we need to
  840. // be more rebust than to hang.
  841. SPIS_INFO * pSpisInfo = (SPIS_INFO *) LocalAlloc(LPTR, sizeof(*pSpisInfo));
  842. if (pSpisInfo)
  843. {
  844. BOOL fAsyncOK = TRUE;
  845. pSpisInfo->fFree = (0 != cbSize);
  846. pSpisInfo->pvData = pvParam;
  847. pSpisInfo->uiAction = uiAction;
  848. pSpisInfo->uiParam = uiParam;
  849. pSpisInfo->fWinIni = fWinIni;
  850. pSpisInfo->pDimmedWindow = pDimmedWindow;
  851. // Spawning thread is responsible for addref dimmed window, but not releasing
  852. // that is the repsonsibility of the spawned thread
  853. if (pSpisInfo->pDimmedWindow)
  854. {
  855. pSpisInfo->pDimmedWindow->AddRef();
  856. }
  857. if (pSpisInfo->fFree)
  858. {
  859. pSpisInfo->pvData = LocalAlloc(LPTR, cbSize);
  860. if (!pSpisInfo->pvData)
  861. {
  862. pSpisInfo->pvData = pvParam;
  863. fAsyncOK = FALSE;
  864. pSpisInfo->fFree = FALSE;
  865. }
  866. else
  867. {
  868. CopyMemory(pSpisInfo->pvData, pvParam, cbSize);
  869. }
  870. }
  871. if (fAsyncOK)
  872. SPICreateThread(SystemParametersInfoAsync_WorkerThread, (void *)pSpisInfo);
  873. else
  874. SystemParametersInfoAsync_WorkerThread((void *)pSpisInfo);
  875. }
  876. }
  877. HRESULT GetCurrentUserCustomName(LPWSTR pszDisplayName, DWORD cchSize)
  878. {
  879. HRESULT hr = S_OK;
  880. // It failed, so load "My Custom Theme". This may happen on personal.
  881. LoadString(HINST_THISDLL, IDS_MYCUSTOMTHEME, pszDisplayName, cchSize);
  882. return hr;
  883. }
  884. HRESULT InstallVisualStyle(IThemeManager * pThemeManager, LPCTSTR pszVisualStylePath, LPCTSTR pszVisualStyleColor, LPCTSTR pszVisualStyleSize)
  885. {
  886. HRESULT hr = E_OUTOFMEMORY;
  887. CComVariant varTheme(pszVisualStylePath);
  888. if (varTheme.bstrVal)
  889. {
  890. IThemeScheme * pVisualStyle;
  891. hr = pThemeManager->get_schemeItem(varTheme, &pVisualStyle);
  892. if (SUCCEEDED(hr))
  893. {
  894. CComVariant varStyleName(pszVisualStyleColor);
  895. if (!varStyleName.bstrVal)
  896. hr = E_OUTOFMEMORY;
  897. else
  898. {
  899. IThemeStyle * pThemeStyle;
  900. hr = pVisualStyle->get_item(varStyleName, &pThemeStyle);
  901. if (SUCCEEDED(hr))
  902. {
  903. CComVariant varSizeName(pszVisualStyleSize);
  904. if (!varSizeName.bstrVal)
  905. hr = E_OUTOFMEMORY;
  906. else
  907. {
  908. IThemeSize * pThemeSize;
  909. hr = pThemeStyle->get_item(varSizeName, &pThemeSize);
  910. if (SUCCEEDED(hr))
  911. {
  912. hr = pThemeStyle->put_SelectedSize(pThemeSize);
  913. if (SUCCEEDED(hr))
  914. {
  915. hr = pVisualStyle->put_SelectedStyle(pThemeStyle);
  916. if (SUCCEEDED(hr))
  917. {
  918. hr = pThemeManager->put_SelectedScheme(pVisualStyle);
  919. }
  920. }
  921. pThemeSize->Release();
  922. }
  923. }
  924. pThemeStyle->Release();
  925. }
  926. }
  927. pVisualStyle->Release();
  928. }
  929. }
  930. return hr;
  931. }
  932. // {B2A7FD52-301F-4348-B93A-638C6DE49229}
  933. DEFINE_GUID(CLSID_WMPSkinMngr, 0xB2A7FD52, 0x301F, 0x4348, 0xB9, 0x3A, 0x63, 0x8C, 0x6D, 0xE4, 0x92, 0x29);
  934. // {076F2FA6-ED30-448B-8CC5-3F3EF3529C7A}
  935. DEFINE_GUID(IID_IWMPSkinMngr, 0x076F2FA6, 0xED30, 0x448B, 0x8C, 0xC5, 0x3F, 0x3E, 0xF3, 0x52, 0x9C, 0x7A);
  936. HRESULT ApplyVisualStyle(LPCTSTR pszVisualStylePath, LPCTSTR pszVisualStyleColor, LPCTSTR pszVisualStyleSize)
  937. {
  938. HRESULT hr = S_OK;
  939. // Load the skin
  940. hr = SetSystemVisualStyle(pszVisualStylePath, pszVisualStyleColor, pszVisualStyleSize, 0);
  941. LogStatus("SetSystemVisualStyle(%ls. %ls, %ls) returned hr=%#08lx.\r\n", pszVisualStylePath, pszVisualStyleColor, pszVisualStyleSize, hr);
  942. if (SUCCEEDED(hr))
  943. {
  944. CComBSTR bstrPath(pszVisualStylePath);
  945. if (pszVisualStylePath && !bstrPath)
  946. {
  947. hr = E_OUTOFMEMORY;
  948. }
  949. else
  950. {
  951. IWMPSkinMngr * pWMPSkinMngr;
  952. // Ignore failures until we are guarenteed they are in setup.
  953. if (SUCCEEDED(CoCreateInstance(CLSID_WMPSkinMngr, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IWMPSkinMngr, &pWMPSkinMngr))))
  954. {
  955. pWMPSkinMngr->SetVisualStyle(bstrPath);
  956. pWMPSkinMngr->Release();
  957. }
  958. }
  959. }
  960. return hr;
  961. }
  962. HRESULT GetPageByCLSID(IUnknown * punkSite, const GUID * pClsid, IPropertyBag ** ppPropertyBag)
  963. {
  964. HRESULT hr = E_FAIL;
  965. *ppPropertyBag = NULL;
  966. if (punkSite)
  967. {
  968. IThemeUIPages * pThemeUI;
  969. hr = punkSite->QueryInterface(IID_PPV_ARG(IThemeUIPages, &pThemeUI));
  970. if (SUCCEEDED(hr))
  971. {
  972. IEnumUnknown * pEnumUnknown;
  973. hr = pThemeUI->GetBasePagesEnum(&pEnumUnknown);
  974. if (SUCCEEDED(hr))
  975. {
  976. IUnknown * punk;
  977. // This may not exit due to policy
  978. hr = IEnumUnknown_FindCLSID(pEnumUnknown, *pClsid, &punk);
  979. if (SUCCEEDED(hr))
  980. {
  981. hr = punk->QueryInterface(IID_PPV_ARG(IPropertyBag, ppPropertyBag));
  982. punk->Release();
  983. }
  984. pEnumUnknown->Release();
  985. }
  986. pThemeUI->Release();
  987. }
  988. }
  989. return hr;
  990. }
  991. DWORD QueryThemeServicesWrap(void)
  992. {
  993. DWORD dwResult = QueryThemeServices();
  994. if (IsTSPerfFlagEnabled(TSPerFlag_NoVisualStyles))
  995. {
  996. dwResult = (dwResult & ~QTS_AVAILABLE); // Remove the QTS_AVAILABLE flag because they are forced of because of TS Perf Flags
  997. LogStatus("Visual Styles Forced off because of TS Perf Flags\r\n");
  998. }
  999. LogStatus("QueryThemeServices() returned %d. In QueryThemeServicesWrap\r\n", dwResult);
  1000. return dwResult;
  1001. }
  1002. void PathUnExpandEnvStringsWrap(LPTSTR pszString, DWORD cchSize)
  1003. {
  1004. TCHAR szTemp[MAX_PATH];
  1005. StringCchCopy(szTemp, ARRAYSIZE(szTemp), pszString);
  1006. if (!PathUnExpandEnvStrings(szTemp, pszString, cchSize))
  1007. {
  1008. StringCchCopy(pszString, cchSize, szTemp);
  1009. }
  1010. }
  1011. void PathExpandEnvStringsWrap(LPTSTR pszString, DWORD cchSize)
  1012. {
  1013. TCHAR szTemp[MAX_PATH];
  1014. StringCchCopy(szTemp, ARRAYSIZE(szTemp), pszString);
  1015. if (0 == SHExpandEnvironmentStrings(szTemp, pszString, cchSize))
  1016. {
  1017. StringCchCopy(pszString, cchSize, szTemp);
  1018. }
  1019. }
  1020. // PERF: This API is INCREADIBLY slow so be very very careful when you use it.
  1021. BOOL EnumDisplaySettingsExWrap(LPCTSTR lpszDeviceName, DWORD iModeNum, LPDEVMODE lpDevMode, DWORD dwFlags)
  1022. {
  1023. DEBUG_CODE(DebugStartWatch());
  1024. BOOL fReturn = EnumDisplaySettingsEx(lpszDeviceName, iModeNum, lpDevMode, dwFlags);
  1025. DEBUG_CODE(TraceMsg(TF_THEMEUI_PERF, "EnumDisplaySettingsEx() took Time=%lums", DebugStopWatch()));
  1026. return fReturn;
  1027. }
  1028. void SystemPathAppend(TCHAR *pszPath, TCHAR *pszMore)
  1029. {
  1030. if (!GetSystemDirectory(pszPath, MAX_PATH) || !PathAppend(pszPath, pszMore))
  1031. {
  1032. StringCchCopy(pszPath, MAX_PATH, pszMore);
  1033. }
  1034. }