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.

390 lines
10 KiB

  1. //---------------------------------------------------------------------------
  2. // ThemeFile.cpp - manages loaded theme files
  3. //---------------------------------------------------------------------------
  4. #include "stdafx.h"
  5. #include "ThemeFile.h"
  6. #include "Loader.h"
  7. #include "Services.h"
  8. //---------------------------------------------------------------------------
  9. CUxThemeFile::CUxThemeFile()
  10. {
  11. strcpy(_szHead, "thmfile");
  12. strcpy(_szTail, "end");
  13. Reset();
  14. }
  15. //---------------------------------------------------------------------------
  16. CUxThemeFile::~CUxThemeFile()
  17. {
  18. if (_pbThemeData || _hMemoryMap)
  19. CloseFile();
  20. strcpy(_szHead, "deleted");
  21. }
  22. //---------------------------------------------------------------------------
  23. __inline bool CUxThemeFile::IsReady()
  24. {
  25. THEMEHDR *hdr = (THEMEHDR *)_pbThemeData;
  26. if (hdr != NULL && ((hdr->dwFlags & SECTION_READY) != 0))
  27. {
  28. return true;
  29. }
  30. return false;
  31. }
  32. //---------------------------------------------------------------------------
  33. __inline bool CUxThemeFile::IsGlobal()
  34. {
  35. THEMEHDR *hdr = (THEMEHDR *)_pbThemeData;
  36. if (hdr != NULL && ((hdr->dwFlags & SECTION_GLOBAL) != 0))
  37. {
  38. return true;
  39. }
  40. return false;
  41. }
  42. //---------------------------------------------------------------------------
  43. __inline bool CUxThemeFile::HasStockObjects()
  44. {
  45. THEMEHDR *hdr = (THEMEHDR *)_pbThemeData;
  46. if (hdr != NULL && ((hdr->dwFlags & SECTION_HASSTOCKOBJECTS) != 0))
  47. {
  48. return true;
  49. }
  50. return false;
  51. }
  52. //---------------------------------------------------------------------------
  53. HRESULT CUxThemeFile::CreateFile(int iLength, BOOL fReserve)
  54. {
  55. Log(LOG_TM, L"CUxThemeFile::CreateFile");
  56. HRESULT hr = S_OK;
  57. if (_pbThemeData)
  58. CloseFile();
  59. //---- we rely on all theme section names containing "ThemeSection" in CHK build so ----
  60. //---- devs/testers can verify that all handles to old theme sections are released. ----
  61. //---- For FRE builds, we want a NULL name for security reasons. ----
  62. WCHAR *pszName = NULL;
  63. #ifdef DEBUG
  64. WCHAR szSectionName[MAX_PATH];
  65. wsprintf(szSectionName, L"Debug_Create_ThemeSection_%d_%d", GetProcessWindowStation(),
  66. GetTickCount());
  67. pszName = szSectionName;
  68. #endif
  69. _hMemoryMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
  70. PAGE_READWRITE | (fReserve ? SEC_RESERVE : 0), 0, iLength, pszName);
  71. if (! _hMemoryMap)
  72. {
  73. Log(LOG_ALWAYS, L"CUxThemeFile::CreateFile: could not create shared memory mapping");
  74. hr = MakeErrorLast();
  75. goto exit;
  76. }
  77. _pbThemeData = (BYTE *)MapViewOfFile(_hMemoryMap, FILE_MAP_WRITE, 0, 0, 0);
  78. if (! _pbThemeData)
  79. {
  80. Log(LOG_ALWAYS, L"CUxThemeFile::CreateFile: could not create shared memory view");
  81. CloseHandle(_hMemoryMap);
  82. hr = MakeErrorLast();
  83. goto exit;
  84. }
  85. Log(LOG_TMHANDLE, L"CUxThemeFile::CreateFile FILE CREATED: len=%d, addr=0x%x",
  86. iLength, _pbThemeData);
  87. exit:
  88. if (FAILED(hr))
  89. Reset();
  90. return hr;
  91. }
  92. //---------------------------------------------------------------------------
  93. HRESULT CUxThemeFile::CreateFromSection(HANDLE hSection)
  94. {
  95. Log(LOG_TM, L"CUxThemeFile::CreateFromSection");
  96. HRESULT hr = S_OK;
  97. void *pvOld = NULL;
  98. //---- ensure we start with all previous handles closed ----
  99. if (_pbThemeData)
  100. CloseFile();
  101. //---- get access to source section data ----
  102. pvOld = MapViewOfFile(hSection, FILE_MAP_READ, 0, 0, 0);
  103. if (! pvOld)
  104. {
  105. hr = MakeErrorLast();
  106. goto exit;
  107. }
  108. THEMEHDR *pHdr = (THEMEHDR *)pvOld;
  109. DWORD dwTrueSize = pHdr->dwTotalLength;
  110. //---- we rely on all theme section names containing "ThemeSection" in CHK build so ----
  111. //---- devs/testers can verify that all handles to old theme sections are released. ----
  112. //---- For FRE builds, we want a NULL name for security reasons. ----
  113. WCHAR *pszName = NULL;
  114. #ifdef DEBUG
  115. WCHAR szSectionName[MAX_PATH];
  116. wsprintf(szSectionName, L"Debug_CreateFromSection_ThemeSection_%d_%d", GetProcessWindowStation(),
  117. GetTickCount());
  118. pszName = szSectionName;
  119. #endif
  120. //---- create the new section ----
  121. _hMemoryMap = CreateFileMapping(INVALID_HANDLE_VALUE, NULL,
  122. PAGE_READWRITE, 0, dwTrueSize, pszName);
  123. if (! _hMemoryMap)
  124. {
  125. Log(LOG_ALWAYS, L"CUxThemeFile::CreateFromSection: could not create shared memory mapping");
  126. hr = MakeErrorLast();
  127. goto exit;
  128. }
  129. //---- get access to new section data ----
  130. _pbThemeData = (BYTE *)MapViewOfFile(_hMemoryMap, FILE_MAP_WRITE, 0, 0, 0);
  131. if (! _pbThemeData)
  132. {
  133. hr = MakeErrorLast();
  134. Log(LOG_ALWAYS, L"CThemeFile::CreateFromSection: could not create shared memory view");
  135. goto exit;
  136. }
  137. //---- copy the data from the old section to the new section ----
  138. __try
  139. {
  140. CopyMemory(_pbThemeData, pvOld, dwTrueSize);
  141. }
  142. __except (EXCEPTION_EXECUTE_HANDLER)
  143. {
  144. hr = GetExceptionCode();
  145. goto exit;
  146. }
  147. //---- ensure version, checksum, etc. is all looking good ----
  148. hr = ValidateThemeData(TRUE);
  149. if (FAILED(hr))
  150. goto exit;
  151. Log(LOG_TMHANDLE, L"CUxThemeFile::CreateFromSection FILE CREATED: addr=0x%x",
  152. _pbThemeData);
  153. exit:
  154. if (pvOld != NULL)
  155. UnmapViewOfFile(pvOld);
  156. if (FAILED(hr))
  157. CloseFile();
  158. return hr;
  159. }
  160. //---------------------------------------------------------------------------
  161. // If fCleanupOnFailure is FALSE, we won't close the handle passed, even on failure.
  162. //---------------------------------------------------------------------------
  163. HRESULT CUxThemeFile::OpenFromHandle(HANDLE handle, BOOL fCleanupOnFailure)
  164. {
  165. HRESULT hr = S_OK;
  166. if (_pbThemeData)
  167. CloseFile();
  168. _pbThemeData = (BYTE *)MapViewOfFile(handle, FILE_MAP_READ, 0, 0, 0);
  169. if (! _pbThemeData)
  170. {
  171. hr = MakeErrorLast();
  172. goto exit;
  173. }
  174. _hMemoryMap = handle;
  175. //---- ensure data is valid ----
  176. hr = ValidateThemeData(FALSE);
  177. if (FAILED(hr))
  178. {
  179. if (!fCleanupOnFailure)
  180. {
  181. _hMemoryMap = NULL; // don't give up the refcount on the handle
  182. CloseFile();
  183. }
  184. hr = MakeError32(ERROR_BAD_FORMAT);
  185. goto exit;
  186. }
  187. #ifdef DEBUG
  188. THEMEHDR *ph;
  189. ph = (THEMEHDR *)_pbThemeData;
  190. Log(LOG_TMHANDLE, L"CUxThemeFile::OpenFromHandle OPENED: num=%d, addr=0x%x",
  191. ph->iLoadId, _pbThemeData);
  192. #endif
  193. exit:
  194. if (FAILED(hr))
  195. {
  196. if (!fCleanupOnFailure)
  197. {
  198. Reset();
  199. }
  200. else
  201. {
  202. CloseFile();
  203. }
  204. }
  205. return hr;
  206. }
  207. //---------------------------------------------------------------------------
  208. HRESULT CUxThemeFile::ValidateThemeData(BOOL fFullCheck)
  209. {
  210. HRESULT hr = S_OK;
  211. THEMEHDR *hdr;
  212. if (! ValidateObj())
  213. {
  214. hr = MakeError32(ERROR_INTERNAL_ERROR);
  215. goto exit;
  216. }
  217. if (IsBadReadPtr(_pbThemeData, 4)) // sufficient test
  218. {
  219. hr = MakeError32(ERROR_BAD_FORMAT);
  220. goto exit;
  221. }
  222. hdr = (THEMEHDR *)_pbThemeData;
  223. if (0 != memcmp(hdr->szSignature, kszBeginCacheFileSignature, kcbBeginSignature)) // bad ptr
  224. {
  225. #ifdef DEBUG
  226. CHAR szSignature[kcbBeginSignature + 1];
  227. memcpy(szSignature, hdr->szSignature, kcbBeginSignature);
  228. szSignature[kcbBeginSignature] = '\0';
  229. Log(LOG_ERROR, L"ValidateThemeData(): bad header signature: %S", szSignature);
  230. #else
  231. Log(LOG_ERROR, L"ValidateThemeData(): bad header signature");
  232. #endif
  233. hr = MakeError32(ERROR_BAD_FORMAT);
  234. goto exit;
  235. }
  236. if (hdr->dwVersion != THEMEDATA_VERSION)
  237. {
  238. Log(LOG_ALWAYS, L"ValidateThemeData(): wrong theme data version: 0x%x", hdr->dwVersion);
  239. hr = MakeError32(ERROR_BAD_FORMAT);
  240. goto exit;
  241. }
  242. if (!IsReady()) // data not ready to use
  243. {
  244. Log(LOG_ALWAYS, L"ValidateThemeData(): data not READY - hdr->dwFlags=%x", hdr->dwFlags);
  245. hr = MakeError32(ERROR_BAD_FORMAT);
  246. goto exit;
  247. }
  248. if (!fFullCheck) // we are done
  249. goto exit;
  250. //---- check that checksum ----
  251. #ifdef NEVER
  252. if (hdr->dwCheckSum != DataCheckSum())
  253. #else // Whistler:190200:Instead of checking the checksum, check the end of file signature, to avoid paging in everything
  254. if (0 != memcmp(_pbThemeData + hdr->dwTotalLength - kcbEndSignature, kszEndCacheFileSignature, kcbEndSignature))
  255. {
  256. Log(LOG_ERROR, L"ValidateThemeData(): bad end of file signature");
  257. hr = MakeError32(ERROR_BAD_FORMAT);
  258. goto exit;
  259. }
  260. #endif // NEVER
  261. exit:
  262. return hr;
  263. }
  264. //---------------------------------------------------------------------------
  265. DWORD CUxThemeFile::DataCheckSum()
  266. {
  267. DWORD sum = 0;
  268. if (ValidateObj())
  269. {
  270. THEMEHDR *hdr = (THEMEHDR *)_pbThemeData;
  271. DWORD len = hdr->dwTotalLength - sizeof(THEMEHDR);
  272. BYTE *pData = _pbThemeData + sizeof(THEMEHDR);
  273. while (len--)
  274. sum += *pData++;
  275. }
  276. return sum;
  277. }
  278. //---------------------------------------------------------------------------
  279. void CUxThemeFile::CloseFile()
  280. {
  281. #ifdef DEBUG
  282. THEMEHDR *ph = (THEMEHDR *)_pbThemeData;
  283. if (ph != NULL)
  284. {
  285. Log(LOG_TMHANDLE, L"Share CLOSED: num=%d, addr=0x%x",
  286. ph->iLoadId, _pbThemeData);
  287. }
  288. #endif
  289. if (_hMemoryMap && HasStockObjects() && !IsGlobal())
  290. {
  291. CThemeServices::ClearStockObjects(_hMemoryMap);
  292. }
  293. if (_pbThemeData)
  294. UnmapViewOfFile(_pbThemeData);
  295. if (_hMemoryMap)
  296. CloseHandle(_hMemoryMap);
  297. Reset();
  298. }
  299. //---------------------------------------------------------------------------
  300. void CUxThemeFile::Reset()
  301. {
  302. _pbThemeData = NULL;
  303. _hMemoryMap = NULL;
  304. }
  305. //---------------------------------------------------------------------------
  306. BOOL CUxThemeFile::ValidateObj()
  307. {
  308. BOOL fValid = TRUE;
  309. //---- check object quickly ----
  310. if ( (! this)
  311. || (ULONGAT(_szHead) != 'fmht') // "thmf"
  312. || (ULONGAT(&_szHead[4]) != 'eli') // "ile"
  313. || (ULONGAT(_szTail) != 'dne')) // "end"
  314. {
  315. Log(LOG_ERROR, L"*** ERROR: Invalid CUxThemeFile Encountered, addr=0x%08x ****", this);
  316. fValid = FALSE;
  317. }
  318. return fValid;
  319. }
  320. //---------------------------------------------------------------------------
  321. HANDLE CUxThemeFile::Unload()
  322. {
  323. HANDLE handle = _hMemoryMap;
  324. if (_pbThemeData != NULL)
  325. {
  326. UnmapViewOfFile(_pbThemeData);
  327. }
  328. Reset(); // don't free handle
  329. return handle;
  330. }