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.

5855 lines
203 KiB

  1. #include "stdafx.h"
  2. #pragma hdrstop
  3. #include "..\deskfldr.h"
  4. #include "dutil.h"
  5. extern "C" char * __cdecl StrTokEx(char ** pstring, const char * control);
  6. #define DXA_GROWTH_CONST 10
  7. #define ZINDEX_START 1000
  8. #define MAXID_LENGTH 10 //Maximum number of digits in ID string plus 1.
  9. #define TF_DESKSTAT 0
  10. #define TF_DYNAMICHTML 0
  11. IActiveDesktop *g_pActiveDesk = NULL;
  12. #define c_szRegStrDesktop REGSTR_PATH_DESKTOP
  13. #define c_szWallpaper REG_VAL_GENERAL_WALLPAPER
  14. #define c_szBackupWallpaper REG_VAL_GENERAL_BACKUPWALLPAPER
  15. #define c_szPattern TEXT("Pattern")
  16. #define c_szTileWall REG_VAL_GENERAL_TILEWALLPAPER
  17. #define c_szWallpaperStyle REG_VAL_GENERAL_WALLPAPERSTYLE
  18. #define c_szWallpaperTime REG_VAL_GENERAL_WALLPAPERTIME
  19. #define c_szWallpaperLocalTime REG_VAL_GENERAL_WALLPAPERLOCALTIME
  20. #define c_szRefreshDesktop TEXT("RefreshDesktop")
  21. #define c_szBufferedRefresh TEXT("BufferedRefresh")
  22. #define COMP_TYPE 0x00000003
  23. #define COMP_SELECTED 0x00002000
  24. #define COMP_NOSCROLL 0x00004000
  25. #ifdef DEBUG
  26. #define ENTERPROC EnterProcDS
  27. #define EXITPROC ExitProcDS
  28. void EnterProcDS(DWORD dwTraceLevel, LPSTR szFmt, ...);
  29. void ExitProcDS(DWORD dwTraceLevel, LPSTR szFmt, ...);
  30. extern DWORD g_dwDeskStatTrace;
  31. #else
  32. #ifndef CCOVER
  33. #pragma warning(disable:4002)
  34. #define ENTERPROC()
  35. #define EXITPROC()
  36. #else // ccover buildi
  37. // these are needed because of a bug in cl.exe that results in improper processing
  38. // of #pragma when run with cl -P, and then compiling
  39. #define ENTERPROC 1 ? (void) 0 : (void)
  40. #define EXITPROC 1 ? (void) 0 : (void)
  41. #endif //end of ccover
  42. #endif
  43. MAKE_CONST_BSTR(s_sstrBeforeEnd, L"BeforeEnd");
  44. MAKE_CONST_BSTR(s_sstrDeskMovr, L"DeskMovr");
  45. MAKE_CONST_BSTR(s_sstrDeskMovrW, L"DeskMovrW");
  46. MAKE_CONST_BSTR(s_sstrclassid, L"classid");
  47. MAKE_CONST_BSTR(s_sstrEmpty, L"");
  48. STDAPI ParseDesktopComponent(HWND hwndOwner, LPWSTR wszURL, COMPONENT *pInfo);
  49. WCHAR wUnicodeBOM = 0xfeff; // Little endian unicode Byte Order Mark.First byte:0xff, Second byte: 0xfe.
  50. //extern BOOL IsWallpaperDesktopV2(LPCTSTR lpszWallpaper);
  51. CReadFileObj::CReadFileObj(LPCTSTR lpszFileName)
  52. {
  53. //Open the file
  54. if ((_hFile = CreateFile(lpszFileName, GENERIC_READ, FILE_SHARE_READ,
  55. NULL, OPEN_EXISTING,
  56. FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
  57. {
  58. WCHAR wBOM;
  59. DWORD dwBytesRead = 0;
  60. if ((ReadFile(_hFile, (LPVOID)&wBOM, sizeof(WCHAR), &dwBytesRead, NULL)) &&
  61. (dwBytesRead == sizeof(WCHAR)))
  62. {
  63. if (wBOM == wUnicodeBOM)
  64. _iCharset = UNICODE_HTML_CHARSET;
  65. else
  66. {
  67. //Note: Anything other than the little endian unicode file is treated as ansi.
  68. _iCharset = ANSI_HTML_CHARSET;
  69. SetFilePointer(_hFile, 0L, NULL, FILE_BEGIN); //Seek to the begining of the file
  70. }
  71. }
  72. }
  73. }
  74. CReadFileObj::~CReadFileObj()
  75. {
  76. if (_hFile != INVALID_HANDLE_VALUE)
  77. {
  78. CloseHandle(_hFile);
  79. _hFile = NULL;
  80. }
  81. }
  82. //
  83. // This will read and if necessary convert between ANSI and UNICODE
  84. //
  85. HRESULT CReadFileObj::FileReadAndConvertChars(int iDestCharset, LPWSTR lpwszBuff, UINT uiCharsToRead, UINT *puiCharsActuallyRead, UINT *puiCharsConverted)
  86. {
  87. HRESULT hres = S_OK;
  88. DWORD dwCharsRead = 0;
  89. DWORD dwTotalCharsConverted = 0;
  90. if (_hFile != INVALID_HANDLE_VALUE)
  91. {
  92. if (_iCharset == UNICODE_HTML_CHARSET)
  93. {
  94. if (iDestCharset == UNICODE_HTML_CHARSET)
  95. {
  96. hres = FileReadCharsW(lpwszBuff, uiCharsToRead, (UINT *)&dwCharsRead);
  97. dwTotalCharsConverted = dwCharsRead;
  98. }
  99. else
  100. {
  101. //Destination is ansi; Read the UNICODE source and convert to ANSI.
  102. WCHAR wszBuf[INTERNET_MAX_URL_LENGTH + 1]; //Temp buffer to read the UNICODE chars into.
  103. LPSTR lpszBuff = (LPSTR)lpwszBuff;
  104. DWORD dwTotalCharsToRead = (DWORD)uiCharsToRead;
  105. while(dwTotalCharsToRead)
  106. {
  107. DWORD dwCount;
  108. DWORD dwActuallyRead;
  109. // - 1 to give room for a null character at the end.
  110. dwCount = (DWORD)min(dwTotalCharsToRead, (ARRAYSIZE(wszBuf) - 1));
  111. if (ReadFile(_hFile, (LPSTR)wszBuf, dwCount*sizeof(WCHAR), &dwActuallyRead, NULL))
  112. {
  113. DWORD dwConverted;
  114. dwActuallyRead = dwActuallyRead/sizeof(WCHAR);
  115. //Null terminate the source buffer.
  116. wszBuf[dwActuallyRead] = L'\0'; //UNICODE null terminate the source.
  117. //Convert what we just read.
  118. dwConverted = SHUnicodeToAnsi(wszBuf, lpszBuff, dwActuallyRead+1); //+1 for null termination
  119. //Update the count & stuff.
  120. lpszBuff += dwConverted - 1; //Subtract the null.
  121. dwTotalCharsToRead -= dwActuallyRead;
  122. dwCharsRead += dwActuallyRead;
  123. dwTotalCharsConverted += dwConverted - 1; //Subtract the null.
  124. if (dwActuallyRead < dwCount)
  125. break; //We have reached the end of file.
  126. }
  127. else
  128. {
  129. hres = E_FAIL;
  130. break;
  131. }
  132. }
  133. }
  134. }
  135. else
  136. {
  137. //Source file is ANSI. Check the Destination.
  138. if (iDestCharset == ANSI_HTML_CHARSET)
  139. {
  140. //Destination is ANSI too! Cool! No need for conversion!
  141. hres = FileReadCharsA((LPSTR)lpwszBuff, uiCharsToRead, (UINT *)&dwCharsRead);
  142. dwTotalCharsConverted = dwCharsRead;
  143. }
  144. else
  145. {
  146. //Destination is UNICODE! Read the ansi and convert it to UNICODE!
  147. char szBuf[INTERNET_MAX_URL_LENGTH + 1]; //Temp buffer to read the ansi chars into.
  148. DWORD dwTotalCharsToRead = (DWORD)uiCharsToRead;
  149. while(dwTotalCharsToRead)
  150. {
  151. DWORD dwCount;
  152. DWORD dwActuallyRead;
  153. // - 1 to give room for a null character at the end.
  154. dwCount = (DWORD)min(dwTotalCharsToRead, (ARRAYSIZE(szBuf) - 1));
  155. if (ReadFile(_hFile, (LPSTR)szBuf, dwCount, &dwActuallyRead, NULL))
  156. {
  157. DWORD dwConverted;
  158. //Null terminate the source buffer.
  159. szBuf[dwActuallyRead] = '\0'; //ANSI null terminate the source.
  160. //Convert what we just read.
  161. dwConverted = SHAnsiToUnicode(szBuf, lpwszBuff, dwActuallyRead+1); //+1 for null termination
  162. //Update the count & stuff.
  163. lpwszBuff += dwConverted - 1; //Subtract the null.
  164. dwTotalCharsToRead -= dwActuallyRead;
  165. dwCharsRead += dwActuallyRead;
  166. dwTotalCharsConverted += dwConverted - 1; //Subtract the null.
  167. if (dwActuallyRead < dwCount)
  168. break; //We have reached the end of file.
  169. }
  170. else
  171. {
  172. hres = E_FAIL;
  173. break;
  174. }
  175. } //while
  176. }
  177. }
  178. }
  179. else
  180. hres = E_FAIL; //The file handle is bad.
  181. *puiCharsActuallyRead = (UINT)dwCharsRead;
  182. *puiCharsConverted = (UINT)dwTotalCharsConverted;
  183. return hres;
  184. }
  185. HRESULT CReadFileObj::FileReadCharsA(LPSTR lpszBuff, UINT uiCharsToRead, UINT *puiCharsActuallyRead)
  186. {
  187. HRESULT hres = E_FAIL;
  188. DWORD dwCharsRead = 0;
  189. if ((_hFile != INVALID_HANDLE_VALUE) &&
  190. (_iCharset == ANSI_HTML_CHARSET) &&
  191. ReadFile(_hFile, (LPVOID)lpszBuff, (DWORD)(uiCharsToRead), &dwCharsRead, NULL))
  192. {
  193. dwCharsRead = dwCharsRead; //get the number of wchars read.
  194. hres = S_OK;
  195. }
  196. *puiCharsActuallyRead = (UINT)dwCharsRead;
  197. return hres;
  198. }
  199. //
  200. // NOTE: The uiCharsToRead must be atleast one less than the size of the buffer (lpwszBuff)
  201. // because one null may be written at the end of the buffer by SHAnsiToUnicode().
  202. //
  203. HRESULT CReadFileObj::FileReadCharsW(LPWSTR lpwszBuff, UINT uiCharsToRead, UINT *puiCharsActuallyRead)
  204. {
  205. HRESULT hres = E_FAIL;
  206. DWORD dwCharsRead = 0;
  207. if ((_hFile != INVALID_HANDLE_VALUE) &&
  208. (_iCharset == UNICODE_HTML_CHARSET) &&
  209. ReadFile(_hFile, (LPVOID)lpwszBuff, (DWORD)(uiCharsToRead*sizeof(WCHAR)), &dwCharsRead, NULL))
  210. {
  211. dwCharsRead = dwCharsRead/sizeof(WCHAR); //get the number of wchars read.
  212. hres = S_OK;
  213. }
  214. *puiCharsActuallyRead = (UINT)dwCharsRead;
  215. return hres;
  216. }
  217. HRESULT CReadFileObj::FileSeekChars(LONG lCharOffset, DWORD dwOrigin)
  218. {
  219. HRESULT hres = E_FAIL;
  220. if (_hFile != INVALID_HANDLE_VALUE)
  221. {
  222. if (SetFilePointer(_hFile,
  223. lCharOffset*((_iCharset == UNICODE_HTML_CHARSET) ? sizeof(WCHAR) : sizeof(char)),
  224. NULL,
  225. dwOrigin) != INVALID_SET_FILE_POINTER)
  226. hres = S_OK;
  227. }
  228. return hres;
  229. }
  230. HRESULT CReadFileObj::FileGetCurCharOffset(LONG *plCharOffset)
  231. {
  232. HRESULT hres = E_FAIL;
  233. DWORD dwByteOffset = 0;
  234. *plCharOffset = 0;
  235. if (_hFile != INVALID_HANDLE_VALUE)
  236. {
  237. if ((dwByteOffset = SetFilePointer(_hFile,
  238. 0L,
  239. NULL,
  240. FILE_CURRENT)) != INVALID_SET_FILE_POINTER)
  241. {
  242. *plCharOffset = dwByteOffset/((_iCharset == UNICODE_HTML_CHARSET) ? sizeof(WCHAR) : sizeof(char));
  243. hres = S_OK;
  244. }
  245. }
  246. return hres;
  247. }
  248. BOOL GetStringFromReg(HKEY hkey,
  249. LPCTSTR lpszSubkey,
  250. LPCTSTR lpszValueName,
  251. LPTSTR lpszValue,
  252. DWORD cchSizeofValueBuff)
  253. {
  254. DWORD cb = cchSizeofValueBuff * sizeof(lpszValue[0]);
  255. return (ERROR_SUCCESS == SHGetValue(hkey, lpszSubkey, lpszValueName, NULL, lpszValue, &cb));
  256. }
  257. void GetWallpaperFileTime(LPCTSTR pszWallpaper, LPFILETIME lpftFileTime)
  258. {
  259. HANDLE hFile;
  260. BOOL fRet = FALSE;
  261. if ((hFile = CreateFile(pszWallpaper, GENERIC_READ, FILE_SHARE_READ,
  262. NULL, OPEN_EXISTING,
  263. FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE)
  264. {
  265. fRet = GetFileTime(hFile, NULL, NULL, lpftFileTime);
  266. CloseHandle(hFile);
  267. }
  268. if (!fRet)
  269. {
  270. ZeroMemory(lpftFileTime, sizeof(FILETIME));
  271. }
  272. // no return value
  273. }
  274. BOOL HasWallpaperReallyChanged(LPCTSTR pszRegKey, LPTSTR pszOldWallpaper, LPTSTR pszBackupWallpaper, DWORD dwOldWallpaperStyle, DWORD dwNewWallpaperStyle)
  275. {
  276. // we default to TRUE here.
  277. if ((dwOldWallpaperStyle == dwNewWallpaperStyle)
  278. && (0 == lstrcmpi(pszOldWallpaper, pszBackupWallpaper)))
  279. {
  280. // The wallpaper filename and style hasn't changed.
  281. // But, the content of this file could have changed.
  282. // See if the content has changed by looking at the
  283. // last-written date and time stamp on this file.
  284. FILETIME ftOld, ftBack;
  285. DWORD cbBack = sizeof(ftBack);
  286. // if either of these fail, then they will
  287. // remain Zero so the compare will
  288. // be successful.
  289. GetWallpaperFileTime(pszOldWallpaper, &ftOld);
  290. if (ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperTime, NULL, &ftBack, &cbBack))
  291. {
  292. ZeroMemory(&ftBack, sizeof(ftBack));
  293. }
  294. //Get the last written time of the backup wallpaper from registry
  295. if (0 == CompareFileTime(&ftOld, &ftBack))
  296. return FALSE; // everything is the same!
  297. // Win2K QFE bug 10689 (AndrewGr)
  298. // same check, but instead of checking UTC time, check local time converted to UTC time
  299. // this is because FAT disks store local time, not UTC time
  300. FILETIME ftLocalBack, ftLocalBackUtc;
  301. cbBack = sizeof(ftLocalBack);
  302. if (ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperLocalTime, NULL, &ftLocalBack, &cbBack))
  303. {
  304. ZeroMemory(&ftLocalBack, sizeof(ftLocalBack));
  305. }
  306. LocalFileTimeToFileTime(&ftLocalBack, &ftLocalBackUtc);
  307. if (ftOld.dwLowDateTime == ftLocalBackUtc.dwLowDateTime
  308. && (ftOld.dwHighDateTime == ftLocalBackUtc.dwHighDateTime))
  309. // everything is the same!
  310. return FALSE;
  311. }
  312. return TRUE;
  313. }
  314. //-------------------------------------------------------------------------------------------------------------//
  315. // Function: ReadWallpaperStyleFromReg()
  316. //
  317. // This function reads the "TileWallpaper" and the "WallpaperStyle" from the given location
  318. // in the registry.
  319. //
  320. //-------------------------------------------------------------------------------------------------------------//
  321. int GetIntFromReg(HKEY hKey,
  322. LPCTSTR lpszSubkey,
  323. LPCTSTR lpszNameValue,
  324. int iDefault)
  325. {
  326. TCHAR szValue[20];
  327. DWORD dwSizeofValueBuff = sizeof(szValue);
  328. int iRetValue = iDefault;
  329. DWORD dwType;
  330. if ((SHGetValue(hKey, lpszSubkey, lpszNameValue, &dwType, szValue,
  331. &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff)
  332. {
  333. if (dwType == REG_SZ)
  334. {
  335. iRetValue = (int)StrToInt(szValue);
  336. }
  337. }
  338. return iRetValue;
  339. }
  340. void ReadWallpaperStyleFromReg(LPCTSTR pszRegKey, DWORD *pdwWallpaperStyle, BOOL fIgnorePlatforms)
  341. {
  342. if (GetIntFromReg(HKEY_CURRENT_USER, pszRegKey, c_szTileWall, WPSTYLE_TILE))
  343. {
  344. // "Tile" overrides the "Stretch" style.
  345. *pdwWallpaperStyle = WPSTYLE_TILE;
  346. }
  347. else
  348. {
  349. // else, STRETCH or CENTER.
  350. *pdwWallpaperStyle = GetIntFromReg(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperStyle, WPSTYLE_CENTER);
  351. }
  352. }
  353. BOOL CActiveDesktop::_IsDisplayInSafeMode(void)
  354. {
  355. WCHAR wszDisplay[MAX_PATH];
  356. DWORD dwcch = MAX_PATH;
  357. return (SUCCEEDED(GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY))
  358. && (0 == StrCmpW(wszDisplay, REG_DESKCOMP_SAFEMODE_SUFFIX_L)));
  359. }
  360. BOOL ReadPolicyForWallpaper(LPTSTR pszPolicy, DWORD cchPolicy)
  361. {
  362. BOOL fPolicySet = FALSE;
  363. DWORD cb = cchPolicy * sizeof(pszPolicy[0]);
  364. if ((SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_WP_POLICY, c_szWallpaper, NULL, pszPolicy, &cb) == ERROR_SUCCESS) && cb)
  365. {
  366. // even if this value was originally REG_SZ it may still
  367. // have environment vars in it for legacy reasons!
  368. if (SUCCEEDED(PathExpandEnvStringsWrap(pszPolicy, cchPolicy)))
  369. {
  370. fPolicySet = TRUE; //Policy is there!
  371. }
  372. else
  373. {
  374. pszPolicy[0] = 0; // if we couldn't expand correctly, null it out to be safe
  375. }
  376. }
  377. else
  378. {
  379. // See if the TS Perf policy is set to turn it off for perf.
  380. fPolicySet = (IsTSPerfFlagEnabled(TSPerFlag_NoADWallpaper) || IsTSPerfFlagEnabled(TSPerFlag_NoWallpaper)); //No policy is set!
  381. }
  382. return fPolicySet;
  383. }
  384. HRESULT GetWallpaperPath(HKEY hKey, LPCTSTR pszKey, LPCTSTR pszValue, LPCTSTR pszFallback, LPTSTR pszPath, DWORD cchSize)
  385. {
  386. HRESULT hr;
  387. if (GetStringFromReg(hKey, pszKey, pszValue, pszPath, cchSize))
  388. {
  389. hr = PathExpandEnvStringsWrap(pszPath, cchSize);
  390. }
  391. else if (pszFallback)
  392. {
  393. hr = StringCchCopy(pszPath, cchSize, pszFallback);
  394. }
  395. else
  396. {
  397. pszPath[0] = 0;
  398. hr = S_FALSE; // couldn't get it from registry, we null the output buffer, but this is not catastrophic
  399. }
  400. return hr;
  401. }
  402. BOOL ReadPolicyForWPStyle(LPDWORD lpdwStyle)
  403. {
  404. DWORD dwStyle;
  405. DWORD dwType;
  406. TCHAR szValue[20];
  407. DWORD dwSizeofValueBuff = sizeof(szValue);
  408. BOOL fRet = FALSE;
  409. // The caller can passin a NULL, if they are not interested in the actual value and they just
  410. // want to know if this policy is set or not.
  411. if (!lpdwStyle)
  412. lpdwStyle = &dwStyle;
  413. if ((SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_WP_POLICY, c_szWallpaperStyle, &dwType, szValue,
  414. &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff)
  415. {
  416. if (dwType == REG_SZ)
  417. {
  418. *lpdwStyle = (DWORD)StrToInt(szValue);
  419. fRet = TRUE;
  420. }
  421. }
  422. return fRet;
  423. }
  424. BOOL CActiveDesktop::_ReadWallpaper(BOOL fActiveDesktop)
  425. {
  426. ENTERPROC(2, "DS ReadWallpaper()");
  427. TCHAR szDeskcomp[MAX_PATH];
  428. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, _pszScheme);
  429. _fPolicyForWPName = ReadPolicyForWallpaper(_szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper));
  430. _fPolicyForWPStyle = ReadPolicyForWPStyle(&_wpo.dwStyle);
  431. //
  432. // Read in the wallpaper and style from the appropriate registry location.
  433. //
  434. LPCTSTR pszRegKey;
  435. if (fActiveDesktop)
  436. {
  437. pszRegKey = szDeskcomp;
  438. TCHAR szOldWallpaper[MAX_PATH];
  439. DWORD dwOldWallpaperStyle;
  440. // Read the Wallpaper from the Old location.
  441. if (S_OK != GetWallpaperPath(HKEY_CURRENT_USER, c_szRegStrDesktop, c_szWallpaper, NULL, szOldWallpaper, ARRAYSIZE(szOldWallpaper)))
  442. {
  443. return FALSE;
  444. }
  445. // Read wallpaper style from the old location.
  446. ReadWallpaperStyleFromReg((LPCTSTR)c_szRegStrDesktop, &dwOldWallpaperStyle, FALSE);
  447. // Read the wallpaper from the new location too!
  448. if ((!_fPolicyForWPName) || (_IsDisplayInSafeMode()))
  449. {
  450. HRESULT hrPath = GetWallpaperPath(HKEY_CURRENT_USER, pszRegKey, c_szWallpaper, szOldWallpaper, _szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper));
  451. if (S_FALSE == hrPath)
  452. {
  453. pszRegKey = c_szRegStrDesktop;
  454. }
  455. else if (FAILED(hrPath))
  456. {
  457. return FALSE;
  458. }
  459. }
  460. //Read wallpaper style from the new location too!
  461. if (!_fPolicyForWPStyle)
  462. {
  463. ReadWallpaperStyleFromReg(pszRegKey, &_wpo.dwStyle, FALSE);
  464. }
  465. //If there is a Safe mode scheme here do NOT attempt to change wallpaper
  466. if ((!_IsDisplayInSafeMode()) && (!_fPolicyForWPName))
  467. {
  468. //Read what is stored as "Backup" wallpaper.
  469. if (S_OK != GetWallpaperPath(HKEY_CURRENT_USER, pszRegKey, c_szBackupWallpaper, szOldWallpaper, _szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper)))
  470. {
  471. return FALSE;
  472. }
  473. else
  474. {
  475. //See if the Old wallpaper is differnet from the backed up wallpaper
  476. if (HasWallpaperReallyChanged(pszRegKey, szOldWallpaper, _szBackupWallpaper, dwOldWallpaperStyle, _wpo.dwStyle))
  477. {
  478. //They are different. This means that some other app has changed the "Old" wallpaper
  479. //after the last time we backed it up in the registry.
  480. // Make this wallpaper as the Selected wallpaper!
  481. if (FAILED(StringCchCopy(_szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper), szOldWallpaper)))
  482. {
  483. return FALSE;
  484. }
  485. else
  486. {
  487. _wpo.dwStyle = dwOldWallpaperStyle;
  488. _fWallpaperDirty = TRUE;
  489. _fWallpaperChangedDuringInit = TRUE;
  490. }
  491. }
  492. }
  493. }
  494. //Make a backup of the "Old" wallpaper from szOldWallpaper
  495. if (FAILED(StringCchCopy(_szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper), szOldWallpaper)))
  496. {
  497. _szBackupWallpaper[0] = 0; // on failure null it out, this value is just an optimization
  498. }
  499. }
  500. else
  501. {
  502. pszRegKey = c_szRegStrDesktop; //Get it from the old location!
  503. //Since active desktop is not available, read wallpaper from old location.
  504. if (!_fPolicyForWPName)
  505. {
  506. if (S_OK != GetWallpaperPath(HKEY_CURRENT_USER, pszRegKey, c_szWallpaper, NULL, _szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper)))
  507. {
  508. return FALSE;
  509. }
  510. }
  511. //Read the wallpaper style
  512. if (!_fPolicyForWPStyle)
  513. ReadWallpaperStyleFromReg(pszRegKey, &_wpo.dwStyle, TRUE);
  514. //Make a backup of the "Old" wallpaper from _szSelectedWallpaper
  515. if (FAILED(StringCchCopy(_szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper), _szSelectedWallpaper)))
  516. {
  517. _szBackupWallpaper[0] = 0; // on failure null it out, this value is just an optimization
  518. }
  519. }
  520. EXITPROC(2, "DS ReadWallpaper! (_szSelectedWP=>%s<)", _szSelectedWallpaper);
  521. return TRUE;
  522. }
  523. void CActiveDesktop::_ReadPattern(void)
  524. {
  525. ENTERPROC(2, "DS ReadPattern()");
  526. GetStringFromReg(HKEY_CURRENT_USER, c_szRegStrDesktop, c_szPattern, _szSelectedPattern, ARRAYSIZE(_szSelectedPattern));
  527. EXITPROC(2, "DS ReadPattern! (_szSelectedPattern=>%s<)", _szSelectedPattern);
  528. }
  529. void CActiveDesktop::_ReadComponent(HKEY hkey, LPCTSTR pszComp)
  530. {
  531. ENTERPROC(2, "DS ReadComponent(hk=%08X,pszComp=>%s<)", hkey, pszComp);
  532. HKEY hkeyComp;
  533. if (RegOpenKeyEx(hkey, pszComp, 0, KEY_READ, &hkeyComp) == ERROR_SUCCESS)
  534. {
  535. DWORD cbSize;
  536. COMPONENTA comp;
  537. comp.dwSize = sizeof(COMPONENTA);
  538. //
  539. // Read in the source string.
  540. //
  541. cbSize = sizeof(comp.szSource);
  542. if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_SOURCE, NULL, NULL, (LPBYTE)&comp.szSource, &cbSize) != ERROR_SUCCESS)
  543. {
  544. comp.szSource[0] = TEXT('\0');
  545. }
  546. //
  547. // Read in the SubscribedURL string.
  548. //
  549. cbSize = sizeof(comp.szSubscribedURL);
  550. if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_SUBSCRIBED_URL, NULL, NULL, (LPBYTE)&comp.szSubscribedURL, &cbSize) != ERROR_SUCCESS)
  551. {
  552. comp.szSubscribedURL[0] = TEXT('\0');
  553. }
  554. //
  555. // Read in the Friendly name string.
  556. //
  557. cbSize = sizeof(comp.szFriendlyName);
  558. if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_NAME, NULL, NULL, (LPBYTE)&comp.szFriendlyName, &cbSize) != ERROR_SUCCESS)
  559. {
  560. comp.szFriendlyName[0] = TEXT('\0');
  561. }
  562. //
  563. // Read in and parse the flags.
  564. //
  565. DWORD dwFlags;
  566. cbSize = sizeof(dwFlags);
  567. if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_FLAGS, NULL, NULL, (LPBYTE)&dwFlags, &cbSize) != ERROR_SUCCESS)
  568. {
  569. dwFlags = 0;
  570. }
  571. comp.iComponentType = dwFlags & COMP_TYPE;
  572. comp.fChecked = (dwFlags & COMP_SELECTED) != 0;
  573. comp.fNoScroll = (dwFlags & COMP_NOSCROLL) != 0;
  574. comp.fDirty = FALSE; //Reading it fresh from registry; Can't be dirty!
  575. //
  576. // Read in the location.
  577. //
  578. cbSize = sizeof(comp.cpPos);
  579. if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_POSITION, NULL, NULL, (LPBYTE)&comp.cpPos, &cbSize) != ERROR_SUCCESS)
  580. {
  581. ZeroMemory(&comp.cpPos, sizeof(comp.cpPos));
  582. }
  583. //
  584. // In IE4.x, we have a very huge positive number (0x7fffffff) as the COMPONENT_TOP;
  585. // As a result some component's z-index overflowed into the negative range (0x80000003)
  586. // To fix this, we halved the COMPONENT_TOP (0x3fffffff) and also check for negative z-index
  587. // values and covert them to postive values.
  588. if (comp.cpPos.izIndex < 0)
  589. comp.cpPos.izIndex = COMPONENT_TOP;
  590. //
  591. // Make sure the cpPos.dwSize is set to correct value
  592. //
  593. comp.cpPos.dwSize = sizeof(COMPPOS);
  594. //
  595. // Read in the current ItemState
  596. //
  597. cbSize = sizeof(comp.dwCurItemState);
  598. if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_CURSTATE, NULL, NULL, (LPBYTE)&comp.dwCurItemState, &cbSize) != ERROR_SUCCESS)
  599. {
  600. //If the item state is missing, we must be reading from IE4 machine.
  601. comp.dwCurItemState = IS_NORMAL;
  602. }
  603. //
  604. // Read in the Original state info.
  605. //
  606. cbSize = sizeof(comp.csiOriginal);
  607. if ((SHQueryValueEx(hkeyComp, REG_VAL_COMP_ORIGINALSTATEINFO, NULL, NULL, (LPBYTE)&comp.csiOriginal, &cbSize) != ERROR_SUCCESS) ||
  608. (comp.csiOriginal.dwSize != sizeof(comp.csiOriginal)))
  609. {
  610. //If the item state is missing, we must be reading from IE4 machine.
  611. // Set the OriginalState to the default info.
  612. SetStateInfo(&comp.csiOriginal, &comp.cpPos, IS_NORMAL);
  613. comp.csiOriginal.dwHeight = comp.csiOriginal.dwWidth = COMPONENT_DEFAULT_WIDTH;
  614. }
  615. //
  616. // Read in the Restored state info.
  617. //
  618. cbSize = sizeof(comp.csiRestored);
  619. if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_RESTOREDSTATEINFO, NULL, NULL, (LPBYTE)&comp.csiRestored, &cbSize) != ERROR_SUCCESS)
  620. {
  621. //If the item state is missing, we must be reading from IE4 machine.
  622. // Set the restored State to the default info.
  623. SetStateInfo(&comp.csiRestored, &comp.cpPos, IS_NORMAL);
  624. }
  625. //
  626. // Add the component to the component list.
  627. //
  628. AddComponentPrivate(&comp, StrToInt(pszComp));
  629. //
  630. // Increment our counter so we know where to add any new
  631. // components after we're done.
  632. //
  633. _dwNextID++;
  634. RegCloseKey(hkeyComp);
  635. }
  636. EXITPROC(2, "DS ReadComponent!");
  637. }
  638. typedef struct _tagSortStruct {
  639. int ihdsaIndex;
  640. int izIndex;
  641. } SORTSTRUCT;
  642. int CALLBACK pfnComponentSort(LPVOID p1, LPVOID p2, LPARAM lParam)
  643. {
  644. SORTSTRUCT * pss1 = (SORTSTRUCT *)p1;
  645. SORTSTRUCT * pss2 = (SORTSTRUCT *)p2;
  646. if (pss1->izIndex > pss2->izIndex)
  647. return 1;
  648. if (pss1->izIndex < pss2->izIndex)
  649. return -1;
  650. return(0);
  651. }
  652. //
  653. // ModifyZIndex
  654. //
  655. // Little helper function to put the zindex of the windowed and windowless components
  656. // into correct buckets so that zorting will produce a correct order by zindex.
  657. //
  658. // If we don't do this then windowless components may end up zordering above windowed ones.
  659. //
  660. void ModifyZIndex(COMPONENTA * pcomp)
  661. {
  662. if (pcomp->cpPos.izIndex != COMPONENT_TOP) {
  663. if (!IsWindowLessComponent(pcomp))
  664. pcomp->cpPos.izIndex += COMPONENT_TOP_WINDOWLESS;
  665. }
  666. else
  667. {
  668. if (IsWindowLessComponent(pcomp))
  669. pcomp->cpPos.izIndex = COMPONENT_TOP_WINDOWLESS;
  670. }
  671. }
  672. //
  673. // SortAndRationalize
  674. //
  675. // SortAndRationalize will take an unsorted component list and sort it such that the components
  676. // come out in the correct z-index indicated order. It will also rebase the z-index values at
  677. // a known constant so that the z-index values will not grow endlessly. SortAndRationalize also
  678. // imposes windowed vs. windowless criteria to the zindex values such that windowless components
  679. // always zorder under windowed ones.
  680. //
  681. void CActiveDesktop::_SortAndRationalize(void)
  682. {
  683. int icComponents;
  684. HDPA hdpa;
  685. if (_hdsaComponent && ((icComponents = DSA_GetItemCount(_hdsaComponent)) > 1) && (hdpa = DPA_Create(0))) {
  686. COMPONENTA * pcomp;
  687. SORTSTRUCT * pss;
  688. int i, iCur = ZINDEX_START;
  689. BOOL fInsertFailed = FALSE;
  690. HDSA hdsaOld;
  691. // Go through each component and insert it's hdsa-index and zindex into the hdpa
  692. for (i = 0; i < icComponents; i++)
  693. {
  694. if (!(pss = (SORTSTRUCT *)LocalAlloc(LPTR, sizeof(SORTSTRUCT))))
  695. break;
  696. pcomp = (COMPONENTA *)DSA_GetItemPtr(_hdsaComponent, i);
  697. ModifyZIndex(pcomp);
  698. pss->ihdsaIndex = i;
  699. pss->izIndex = pcomp->cpPos.izIndex;
  700. if (DPA_AppendPtr(hdpa, (void FAR *)pss) == -1) {
  701. LocalFree((HANDLE)pss);
  702. break;
  703. }
  704. }
  705. // Sort the hdpa by zindex
  706. DPA_Sort(hdpa, pfnComponentSort, 0);
  707. // Save old values
  708. hdsaOld = _hdsaComponent;
  709. // Null out the old hdsa, so AddComponentPrivate will create a new one
  710. _hdsaComponent = NULL;
  711. // Now go through the sorted hdpa and update the component zindex with a ZINDEX_START based zindex, then
  712. // add the component to the new hdsa in sorted order.
  713. for (i = 0; i < icComponents; i++) {
  714. if (!(pss = (SORTSTRUCT *)DPA_GetPtr(hdpa, i)))
  715. break;
  716. // Get component and update it's zIndex and id
  717. pcomp = (COMPONENTA *)DSA_GetItemPtr(hdsaOld, pss->ihdsaIndex);
  718. pcomp->cpPos.izIndex = iCur;
  719. iCur += 2;
  720. // Free ptr
  721. LocalFree((HANDLE)pss);
  722. // Add to new hdsa in sorted order
  723. if (!fInsertFailed) {
  724. fInsertFailed = !AddComponentPrivate(pcomp, pcomp->dwID);
  725. }
  726. }
  727. // If we're completely successfull then destroy the old hdsa. Otherwise we need
  728. // to destroy the new one and restore the old one.
  729. if ((i == icComponents) && !fInsertFailed) {
  730. DSA_Destroy(hdsaOld);
  731. } else {
  732. if (_hdsaComponent)
  733. DSA_Destroy(_hdsaComponent);
  734. _hdsaComponent = hdsaOld;
  735. }
  736. DPA_Destroy(hdpa);
  737. }
  738. }
  739. void CActiveDesktop::_ReadComponents(BOOL fActiveDesktop)
  740. {
  741. ENTERPROC(2, "DS ReadComponents()");
  742. HKEY hkey;
  743. TCHAR szDeskcomp[MAX_PATH];
  744. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_COMPONENTS, _pszScheme);
  745. if (RegOpenKeyEx(HKEY_CURRENT_USER, szDeskcomp, 0, KEY_READ, &hkey) == ERROR_SUCCESS)
  746. {
  747. DWORD cbSize;
  748. int i = 0;
  749. TCHAR lpszSubkey[MAX_PATH];
  750. //
  751. // Read in the general settings.
  752. //
  753. DWORD dwSettings;
  754. cbSize = sizeof(dwSettings);
  755. if (SHQueryValueEx(hkey, REG_VAL_COMP_SETTINGS, NULL, NULL, (LPBYTE)&dwSettings, &cbSize) == ERROR_SUCCESS)
  756. {
  757. _co.fEnableComponents = (dwSettings & COMPSETTING_ENABLE) != 0;
  758. }
  759. _co.fActiveDesktop = fActiveDesktop;
  760. //
  761. // Read in all the desktop components
  762. //
  763. while (RegEnumKey(hkey, i, lpszSubkey, ARRAYSIZE(lpszSubkey)) == ERROR_SUCCESS)
  764. {
  765. _ReadComponent(hkey, lpszSubkey);
  766. i++;
  767. }
  768. _SortAndRationalize();
  769. RegCloseKey(hkey);
  770. }
  771. EXITPROC(2, "DS ReadComponents!");
  772. }
  773. void CActiveDesktop::_Initialize(void)
  774. {
  775. ENTERPROC(2, "DS Initialize()");
  776. if (!_fInitialized)
  777. {
  778. _fInitialized = TRUE;
  779. InitDeskHtmlGlobals();
  780. SHELLSTATE ss = {0};
  781. SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  782. BOOL fActiveDesktop = BOOLIFY(ss.fDesktopHTML);
  783. _co.dwSize = sizeof(_co);
  784. _wpo.dwSize = sizeof(_wpo);
  785. //
  786. // This per-user registry branch may not exist for this user. Or, even if
  787. // it does exist, it may have some stale info. So ensure that atlreast the
  788. // default components are there and that the html version is current for this
  789. // branch of the registry!
  790. // If everything is current, the following function does nothing!
  791. //
  792. CDeskHtmlProp_RegUnReg(TRUE); //TRUE => install.
  793. _ReadWallpaper(fActiveDesktop);
  794. _ReadPattern();
  795. _ReadComponents(fActiveDesktop);
  796. // If we are in safemode, the we can not use Dynamic Html to make updates because
  797. // updates involve complete change of background Html.
  798. if (_IsDisplayInSafeMode())
  799. _fUseDynamicHtml = FALSE;
  800. else
  801. _fUseDynamicHtml = TRUE; //Any component added after the initialization must go through dynamic html.
  802. _fDirty = FALSE;
  803. _fNeedBodyEnd = FALSE;
  804. }
  805. EXITPROC(2, "DS Initialize!");
  806. }
  807. void CActiveDesktop::_SaveWallpaper(void)
  808. {
  809. ENTERPROC(2, "DS SaveWallpaper");
  810. TCHAR szDeskcomp[MAX_PATH];
  811. BOOL fNormalWallpaper;
  812. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, _pszScheme);
  813. //
  814. // Compute tiling string.
  815. //
  816. TCHAR szTiled[2];
  817. szTiled[0] = TEXT('0') + (TCHAR)(_wpo.dwStyle & WPSTYLE_TILE);
  818. szTiled[1] = NULL;
  819. //
  820. // Compute the Wallpaper styling string
  821. //
  822. TCHAR szWPStyle[2];
  823. //
  824. // NOTE: If WPSTYLE_TILE is set, we still want to say WallpaperStyle="0"; This won't hurt
  825. // because TileWallpaper="1" will over-ride this anyway.
  826. // The reason for this hack is that during memphis setup, they put a tiled wallpaper. Then we
  827. // write WallpaperStyle=1 and TileWallpaper=1 in new and old locations. Then, then change
  828. // the wallpaper and set TileWallpaper=0. Since the WallpaperStyle continues to be 1, they
  829. // get a tiled wallpaper finally. The following is to avoid this problem!
  830. //
  831. szWPStyle[0] = TEXT('0') + (TCHAR)(_wpo.dwStyle & WPSTYLE_STRETCH);
  832. szWPStyle[1] = NULL;
  833. //
  834. // Write out wallpaper settings in new active desktop area.
  835. //
  836. if (_fWallpaperDirty || _fWallpaperChangedDuringInit)
  837. {
  838. if (!_fPolicyForWPStyle)
  839. {
  840. SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
  841. c_szTileWall, REG_SZ, szTiled, CbFromCch(lstrlen(szTiled)+1));
  842. }
  843. //
  844. // Note: We do not write the Wallpaper Style string for older systems because we do not
  845. // want to over-write what PlusPack writes. However, for newer Operating systems, we
  846. // want to write the WallpaperStyle also.
  847. //
  848. if (!_fPolicyForWPStyle)
  849. {
  850. SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
  851. c_szWallpaperStyle, REG_SZ, szWPStyle, CbFromCch(lstrlen(szWPStyle)+1));
  852. }
  853. if (!_fPolicyForWPName)
  854. {
  855. SHRegSetPath(HKEY_CURRENT_USER, szDeskcomp, c_szWallpaper, _szSelectedWallpaper, 0);
  856. }
  857. }
  858. if (fNormalWallpaper = IsNormalWallpaper(_szSelectedWallpaper))
  859. {
  860. if (FAILED(StringCchCopy(_szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper), _szSelectedWallpaper)))
  861. {
  862. _szBackupWallpaper[0] = 0;
  863. }
  864. }
  865. if (!_fPolicyForWPName)
  866. {
  867. FILETIME ft, ftLocal;
  868. GetWallpaperFileTime(_szBackupWallpaper, &ft);
  869. FileTimeToLocalFileTime(&ft, &ftLocal); // for FAT systems to track across DST changes
  870. // Backup the "Old type" wallpaper's name here in the new location
  871. // sothat we can detect when this gets changed by some other app.
  872. SHRegSetPath(HKEY_CURRENT_USER, szDeskcomp, c_szBackupWallpaper, _szBackupWallpaper, 0);
  873. SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
  874. c_szWallpaperTime, REG_BINARY, &ft,
  875. sizeof(ft));
  876. SHSetValue(HKEY_CURRENT_USER, szDeskcomp,
  877. c_szWallpaperLocalTime, REG_BINARY, &ftLocal,
  878. sizeof(ftLocal)); // AndrewGr save local time not UTC time
  879. }
  880. //
  881. // Even if this wallpaper is not valid in normal desktop (i.e., even if it is not a .BMP),
  882. // write it out in normal desktop registry area.
  883. //
  884. if (_fWallpaperDirty)
  885. {
  886. if (!_fPolicyForWPStyle)
  887. {
  888. SHSetValue(HKEY_CURRENT_USER, c_szRegStrDesktop,
  889. c_szTileWall, REG_SZ, szTiled, CbFromCch(lstrlen(szTiled)+1));
  890. }
  891. //
  892. // Note: We do not write the Wallpaper Style string for older systems because we do not
  893. // want to over-write what PlusPack writes. However, for newer Operating systems, we
  894. // want to write the WallpaperStyle also.
  895. //
  896. if (!_fPolicyForWPStyle)
  897. {
  898. SHSetValue(HKEY_CURRENT_USER, c_szRegStrDesktop,
  899. c_szWallpaperStyle, REG_SZ, szWPStyle, CbFromCch(lstrlen(szWPStyle)+1));
  900. }
  901. if (!_fPolicyForWPName)
  902. {
  903. SystemParametersInfo(SPI_SETDESKWALLPAPER, 0,
  904. (fNormalWallpaper ? _szSelectedWallpaper : _szBackupWallpaper),
  905. SPIF_UPDATEINIFILE);
  906. }
  907. }
  908. EXITPROC(2, "DS SaveWallpaper");
  909. }
  910. void CActiveDesktop::_SaveComponent(HKEY hkey, int iIndex, COMPONENTA *pcomp)
  911. {
  912. ENTERPROC(2, "DS SaveComponent(hkey=%08X,iIndex=%d,pcomp=%08X)", hkey, iIndex, pcomp);
  913. TCHAR szSubKey[8];
  914. HKEY hkeySub;
  915. if (SUCCEEDED(StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), iIndex)))
  916. {
  917. if (ERROR_SUCCESS == RegCreateKeyEx(hkey, szSubKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkeySub, 0))
  918. {
  919. pcomp->fDirty = FALSE; //Since we are saving in the registry, reset this!
  920. //
  921. // Write out the source string and Friendly name string.
  922. //
  923. RegSetValueEx(hkeySub, REG_VAL_COMP_SOURCE, 0, REG_SZ, (LPBYTE)pcomp->szSource, (lstrlen(pcomp->szSource)+1)*sizeof(TCHAR));
  924. RegSetValueEx(hkeySub, REG_VAL_COMP_SUBSCRIBED_URL, 0, REG_SZ, (LPBYTE)pcomp->szSubscribedURL, (lstrlen(pcomp->szSubscribedURL)+1)*sizeof(TCHAR));
  925. RegSetValueEx(hkeySub, REG_VAL_COMP_NAME, 0, REG_SZ, (LPBYTE)pcomp->szFriendlyName, (lstrlen(pcomp->szFriendlyName)+1)*sizeof(TCHAR));
  926. //
  927. // Compute and write out flags.
  928. //
  929. DWORD dwFlags = 0;
  930. dwFlags |= pcomp->iComponentType;
  931. if (pcomp->fChecked)
  932. {
  933. dwFlags |= COMP_SELECTED;
  934. }
  935. if (pcomp->fNoScroll)
  936. {
  937. dwFlags |= COMP_NOSCROLL;
  938. }
  939. RegSetValueEx(hkeySub, REG_VAL_COMP_FLAGS, 0, REG_DWORD, (LPBYTE)&dwFlags, sizeof(dwFlags));
  940. //
  941. // Write out the position.
  942. //
  943. RegSetValueEx(hkeySub, REG_VAL_COMP_POSITION, 0, REG_BINARY, (LPBYTE)&pcomp->cpPos, sizeof(pcomp->cpPos));
  944. // Write out the Current state
  945. RegSetValueEx(hkeySub, REG_VAL_COMP_CURSTATE, 0, REG_DWORD, (LPBYTE)&pcomp->dwCurItemState, sizeof(pcomp->dwCurItemState));
  946. // Write out the Original State Info
  947. RegSetValueEx(hkeySub, REG_VAL_COMP_ORIGINALSTATEINFO, 0, REG_BINARY, (LPBYTE)&pcomp->csiOriginal, sizeof(pcomp->csiOriginal));
  948. // Write out the Restored State Info
  949. RegSetValueEx(hkeySub, REG_VAL_COMP_RESTOREDSTATEINFO, 0, REG_BINARY, (LPBYTE)&pcomp->csiRestored, sizeof(pcomp->csiRestored));
  950. RegCloseKey(hkeySub);
  951. }
  952. }
  953. EXITPROC(2, "DS SaveComponent!");
  954. }
  955. void CActiveDesktop::_SaveComponents(void)
  956. {
  957. ENTERPROC(2, "DS SaveComponents");
  958. DWORD dwFlags = 0, dwDataLength = sizeof(dwFlags);
  959. int i;
  960. TCHAR szDeskcomp[MAX_PATH];
  961. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_COMPONENTS, _pszScheme);
  962. //
  963. // We need to preserve the old GENFLAGS, so read them now before we roach them.
  964. //
  965. SHGetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_COMP_GENFLAGS, NULL,
  966. &dwFlags, &dwDataLength);
  967. //
  968. // Delete the entire registry key.
  969. //
  970. SHDeleteKey(HKEY_CURRENT_USER, szDeskcomp);
  971. //
  972. // Recreate the registry key.
  973. //
  974. HKEY hkey;
  975. if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, szDeskcomp, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, 0))
  976. {
  977. //
  978. // Write out the version number.
  979. //
  980. DWORD dw = CUR_DESKHTML_VERSION;
  981. RegSetValueEx(hkey, REG_VAL_COMP_VERSION, 0, REG_DWORD, (LPBYTE)(&dw), sizeof(dw));
  982. dw = CUR_DESKHTML_MINOR_VERSION;
  983. RegSetValueEx(hkey, REG_VAL_COMP_MINOR_VERSION, 0, REG_DWORD, (LPBYTE)(&dw), sizeof(dw));
  984. //
  985. // Write out the general settings.
  986. //
  987. DWORD dwSettings = 0;
  988. if (_co.fEnableComponents)
  989. {
  990. dwSettings |= COMPSETTING_ENABLE;
  991. }
  992. RegSetValueEx(hkey, REG_VAL_COMP_SETTINGS, 0, REG_DWORD, (LPBYTE)&dwSettings, sizeof(dwSettings));
  993. //
  994. // Write out the general flags
  995. //
  996. RegSetValueEx(hkey, REG_VAL_COMP_GENFLAGS, 0, REG_DWORD, (LPBYTE)&dwFlags, sizeof(dwFlags));
  997. if (_hdsaComponent)
  998. {
  999. //
  1000. // Write out the settings for each component
  1001. //
  1002. for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  1003. {
  1004. COMPONENTA * pcomp;
  1005. if (pcomp = (COMPONENTA *)DSA_GetItemPtr(_hdsaComponent, i))
  1006. {
  1007. pcomp->dwID = i;
  1008. _SaveComponent(hkey, i, pcomp);
  1009. }
  1010. }
  1011. }
  1012. RegCloseKey(hkey);
  1013. }
  1014. EXITPROC(2, "DS SaveComponents");
  1015. }
  1016. void CActiveDesktop::_SavePattern(DWORD dwFlags)
  1017. {
  1018. ENTERPROC(2, "DS SavePattern()");
  1019. if (_fPatternDirty && (dwFlags & SAVE_PATTERN_NAME))
  1020. {
  1021. //
  1022. // Write out the pattern to the registry and INI files.
  1023. //
  1024. SystemParametersInfo(SPI_SETDESKPATTERN, 0, _szSelectedPattern, SPIF_UPDATEINIFILE);
  1025. }
  1026. if (IsValidPattern(_szSelectedPattern) && (dwFlags & GENERATE_PATTERN_FILE))
  1027. {
  1028. //
  1029. // Write out the pattern as a BMP file for use in HTML.
  1030. //
  1031. TCHAR szBitmapFile[MAX_PATH];
  1032. HANDLE hFileBitmap = INVALID_HANDLE_VALUE;
  1033. if (SUCCEEDED(GetPerUserFileName(szBitmapFile, ARRAYSIZE(szBitmapFile), PATTERN_FILENAME)))
  1034. {
  1035. hFileBitmap = CreateFile(szBitmapFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  1036. FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL);
  1037. }
  1038. if (hFileBitmap != INVALID_HANDLE_VALUE)
  1039. {
  1040. DWORD cbWritten;
  1041. BITMAPFILEHEADER bmfh = {0};
  1042. bmfh.bfType = 0x4D42; // 'BM'
  1043. bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD) + 8*sizeof(DWORD);
  1044. bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD);
  1045. WriteFile(hFileBitmap, &bmfh, sizeof(bmfh), &cbWritten, NULL);
  1046. BITMAPINFOHEADER bmih = {0};
  1047. bmih.biSize = sizeof(BITMAPINFOHEADER);
  1048. bmih.biWidth = 8;
  1049. bmih.biHeight = 8;
  1050. bmih.biPlanes = 1;
  1051. bmih.biBitCount = 1;
  1052. bmih.biCompression = BI_RGB;
  1053. WriteFile(hFileBitmap, &bmih, sizeof(bmih), &cbWritten, NULL);
  1054. RGBQUAD argbTable[2] = {0};
  1055. DWORD rgb;
  1056. rgb = GetSysColor(COLOR_BACKGROUND);
  1057. argbTable[0].rgbBlue = GetBValue(rgb);
  1058. argbTable[0].rgbGreen = GetGValue(rgb);
  1059. argbTable[0].rgbRed = GetRValue(rgb);
  1060. rgb = GetSysColor(COLOR_WINDOWTEXT);
  1061. argbTable[1].rgbBlue = GetBValue(rgb);
  1062. argbTable[1].rgbGreen = GetGValue(rgb);
  1063. argbTable[1].rgbRed = GetRValue(rgb);
  1064. WriteFile(hFileBitmap, argbTable, sizeof(argbTable), &cbWritten, NULL);
  1065. DWORD adwBits[8];
  1066. PatternToDwords(_szSelectedPattern, adwBits);
  1067. WriteFile(hFileBitmap, adwBits, sizeof(adwBits), &cbWritten, NULL);
  1068. CloseHandle(hFileBitmap);
  1069. }
  1070. }
  1071. EXITPROC(2, "DS SavePattern!");
  1072. }
  1073. void CActiveDesktop::_WriteHtmlFromString(LPCTSTR psz)
  1074. {
  1075. ENTERPROC(3, "DS WriteHtmlFromString(psz=>%s<)", psz);
  1076. LPCWSTR pwsz;
  1077. WCHAR szBuf[INTERNET_MAX_URL_LENGTH];
  1078. UINT uiLen;
  1079. int cch;
  1080. if ((_pStream == NULL) && (_iDestFileCharset == ANSI_HTML_CHARSET))
  1081. {
  1082. cch = SHUnicodeToAnsi(psz, (LPSTR)szBuf, ARRAYSIZE(szBuf));
  1083. ASSERT(cch == lstrlenW((LPWSTR)psz)+1);
  1084. pwsz = (LPCWSTR)szBuf;
  1085. uiLen = lstrlenA((LPSTR)szBuf);
  1086. }
  1087. else
  1088. {
  1089. pwsz = psz;
  1090. uiLen = lstrlenW(pwsz);
  1091. }
  1092. UINT cbWritten;
  1093. _WriteHtmlW(pwsz, uiLen, &cbWritten);
  1094. EXITPROC(3, "DS WriteHtmlFromString!");
  1095. }
  1096. void CActiveDesktop::_WriteHtmlFromId(UINT uid)
  1097. {
  1098. ENTERPROC(3, "DS WriteHtmlFromId(uid=%d)", uid);
  1099. TCHAR szBuf[INTERNET_MAX_URL_LENGTH];
  1100. LoadString(HINST_THISDLL, uid, szBuf, ARRAYSIZE(szBuf));
  1101. _WriteHtmlFromString(szBuf);
  1102. EXITPROC(3, "DS WriteHtmlFromId!");
  1103. }
  1104. void CActiveDesktop::_WriteHtmlFromIdF(UINT uid, ...)
  1105. {
  1106. ENTERPROC(3, "DS WriteHtmlFromIdF(uid=%d,...)", uid);
  1107. TCHAR szBufFmt[INTERNET_MAX_URL_LENGTH];
  1108. TCHAR szBuf[INTERNET_MAX_URL_LENGTH];
  1109. LoadString(HINST_THISDLL, uid, szBufFmt, ARRAYSIZE(szBufFmt));
  1110. va_list arglist;
  1111. va_start(arglist, uid);
  1112. HRESULT hr = StringCchVPrintf(szBuf, ARRAYSIZE(szBuf), szBufFmt, arglist);
  1113. va_end(arglist);
  1114. if (SUCCEEDED(hr))
  1115. {
  1116. _WriteHtmlFromString(szBuf);
  1117. }
  1118. EXITPROC(3, "DS WriteHtmlFromIdF!");
  1119. }
  1120. void CActiveDesktop::_WriteHtmlFromFile(LPCTSTR pszContents)
  1121. {
  1122. ENTERPROC(3, "DS WriteHtmlFromFile(pszContents=>%s<)", pszContents);
  1123. CReadFileObj *pReadFileObj = new CReadFileObj(pszContents);
  1124. if (pReadFileObj)
  1125. {
  1126. if (pReadFileObj->_hFile != INVALID_HANDLE_VALUE)
  1127. {
  1128. WCHAR wcBuf[INTERNET_MAX_URL_LENGTH + 1];
  1129. UINT uiCharCount = ARRAYSIZE(wcBuf) -1; //Leave room for null termination.
  1130. UINT uiCharsRead;
  1131. UINT uiCharsConverted;
  1132. int iDestCharset = (_pStream ? UNICODE_HTML_CHARSET : _iDestFileCharset);
  1133. while (SUCCEEDED(pReadFileObj->FileReadAndConvertChars(iDestCharset, wcBuf, uiCharCount, &uiCharsRead, &uiCharsConverted)) && uiCharsRead)
  1134. {
  1135. UINT cbWritten;
  1136. _WriteHtmlW(wcBuf, uiCharsConverted, &cbWritten);
  1137. if (uiCharsRead < uiCharCount)
  1138. {
  1139. break;
  1140. }
  1141. }
  1142. }
  1143. delete pReadFileObj;
  1144. }
  1145. EXITPROC(3, "DS WriteHtmlFromFile!");
  1146. }
  1147. void CActiveDesktop::_WriteHtmlFromReadFileObj(CReadFileObj *pFileObj, int iOffsetStart, int iOffsetEnd)
  1148. {
  1149. ENTERPROC(3, "DS WriteHtmlFromReadFileObj(pFileObj=%08X,iOffsetStart=%d,iOffsetEnd=%d)", pFileObj, iOffsetStart, iOffsetEnd);
  1150. if (iOffsetStart != -1)
  1151. {
  1152. pFileObj->FileSeekChars(iOffsetStart, FILE_BEGIN);
  1153. }
  1154. else
  1155. {
  1156. ASSERT(iOffsetEnd == -1);
  1157. iOffsetEnd = -1;
  1158. }
  1159. //Get the number of WIDECHARs to be written
  1160. UINT cchWrite = (iOffsetEnd == -1) ? 0xFFFFFFFF : (iOffsetEnd - iOffsetStart);
  1161. while (cchWrite)
  1162. {
  1163. WCHAR wcBuf[INTERNET_MAX_URL_LENGTH+1];
  1164. //
  1165. // Read a chunk.
  1166. //
  1167. UINT cchTryRead = (UINT)min(cchWrite, (ARRAYSIZE(wcBuf) - 1));
  1168. UINT cchActualRead;
  1169. HRESULT hres;
  1170. //Note: if we are reading ANSI, we still use the unicode buff; but cast it!
  1171. if (_iDestFileCharset == ANSI_HTML_CHARSET)
  1172. hres = pFileObj->FileReadCharsA((LPSTR)wcBuf, cchTryRead, &cchActualRead);
  1173. else
  1174. hres = pFileObj->FileReadCharsW(wcBuf, cchTryRead, &cchActualRead);
  1175. if (SUCCEEDED(hres) && cchActualRead)
  1176. {
  1177. //
  1178. // Write a chunk.
  1179. //
  1180. UINT cchWritten;
  1181. _WriteHtmlW(wcBuf, cchActualRead, &cchWritten);
  1182. if (cchActualRead < cchTryRead)
  1183. {
  1184. //
  1185. // End of file, all done.
  1186. //
  1187. break;
  1188. }
  1189. cchWrite -= cchActualRead;
  1190. }
  1191. else
  1192. {
  1193. //
  1194. // Error reading from file, all done.
  1195. //
  1196. break;
  1197. }
  1198. }
  1199. EXITPROC(3, "DS WriteHtmlFromHfile!");
  1200. }
  1201. int CActiveDesktop::_ScanForTagA(CReadFileObj *pFileObj, int iOffsetStart, LPCSTR pszTag)
  1202. {
  1203. ENTERPROC(2, "DS ScanForTagA(pFileObj=%08X,iOffsetStart=%d,pszTagA=>%s<)",
  1204. pFileObj, iOffsetStart, pszTag);
  1205. int iRet = -1;
  1206. BOOL fDoneReading = FALSE;
  1207. int iOffset;
  1208. DWORD cchTag = lstrlenA(pszTag);
  1209. pFileObj->FileSeekChars(iOffsetStart, FILE_BEGIN);
  1210. iOffset = iOffsetStart;
  1211. DWORD cchBuf = 0;
  1212. while (!fDoneReading)
  1213. {
  1214. char szBuf[INTERNET_MAX_URL_LENGTH+1];
  1215. //
  1216. // Fill in the buffer.
  1217. //
  1218. UINT cchTryRead = ARRAYSIZE(szBuf) - cchBuf - 1;
  1219. UINT cchRead;
  1220. if (SUCCEEDED(pFileObj->FileReadCharsA(&szBuf[cchBuf], cchTryRead, &cchRead)) && cchRead)
  1221. {
  1222. cchBuf += cchRead;
  1223. //
  1224. // Terminate the string.
  1225. //
  1226. szBuf[cchBuf] = '\0';
  1227. //
  1228. // Scan for the tag.
  1229. //
  1230. LPSTR pszTagInBuf = StrStrIA(szBuf, pszTag);
  1231. if (pszTagInBuf)
  1232. {
  1233. //
  1234. // Found the tag, compute the offset.
  1235. //
  1236. iRet = (int) (iOffset + pszTagInBuf - szBuf);
  1237. fDoneReading = TRUE;
  1238. }
  1239. else if (cchRead < cchTryRead)
  1240. {
  1241. //
  1242. // Ran out of file without finding tag.
  1243. //
  1244. fDoneReading = TRUE;
  1245. }
  1246. else
  1247. {
  1248. //
  1249. // Compute how many bytes we want to throw away
  1250. // from this buffer so we can read in more data.
  1251. // We don't want to throw away all the bytes because
  1252. // the tag we want may span two buffers.
  1253. //
  1254. DWORD cchSkip = cchBuf - cchTag;
  1255. //
  1256. // Advance the file offset.
  1257. //
  1258. iOffset += cchSkip;
  1259. //
  1260. // Reduce the buffer size.
  1261. //
  1262. cchBuf -= cchSkip;
  1263. //
  1264. // Move the kept bytes to the beginning of the buffer.
  1265. //
  1266. MoveMemory(szBuf, szBuf + cchSkip, cchBuf * sizeof(szBuf[0]));
  1267. }
  1268. }
  1269. else
  1270. {
  1271. fDoneReading = TRUE;
  1272. }
  1273. }
  1274. EXITPROC(2, "DS ScanForTagA=%d", iRet);
  1275. return iRet;
  1276. }
  1277. int CActiveDesktop::_ScanForTagW(CReadFileObj *pFileObj, int iOffsetStart, LPCWSTR pwszTag)
  1278. {
  1279. ENTERPROC(2, "DS ScanForTag(pFileObj=%08X,iOffsetStart=%d,pszTagA=>%s<)",
  1280. pFileObj, iOffsetStart, pwszTag);
  1281. int iRet = -1;
  1282. BOOL fDoneReading = FALSE;
  1283. int iOffset;
  1284. DWORD cchTag = lstrlenW(pwszTag);
  1285. pFileObj->FileSeekChars(iOffsetStart, FILE_BEGIN);
  1286. iOffset = iOffsetStart;
  1287. DWORD cchBuf = 0;
  1288. while (!fDoneReading)
  1289. {
  1290. WCHAR wszBuf[INTERNET_MAX_URL_LENGTH+1];
  1291. //
  1292. // Fill in the buffer.
  1293. //
  1294. UINT cchTryRead = ARRAYSIZE(wszBuf) - cchBuf - 1;
  1295. UINT cchRead;
  1296. if (SUCCEEDED(pFileObj->FileReadCharsW(&wszBuf[cchBuf], cchTryRead, &cchRead)) && cchRead)
  1297. {
  1298. cchBuf += cchRead;
  1299. //
  1300. // Terminate the string.
  1301. //
  1302. wszBuf[cchBuf] = L'\0';
  1303. //
  1304. // Scan for the tag.
  1305. //
  1306. LPWSTR pwszTagInBuf = StrStrIW(wszBuf, pwszTag);
  1307. if (pwszTagInBuf)
  1308. {
  1309. //
  1310. // Found the tag, compute the offset.
  1311. //
  1312. iRet = (int) (iOffset + pwszTagInBuf - wszBuf);
  1313. fDoneReading = TRUE;
  1314. }
  1315. else if (cchRead < cchTryRead)
  1316. {
  1317. //
  1318. // Ran out of file without finding tag.
  1319. //
  1320. fDoneReading = TRUE;
  1321. }
  1322. else
  1323. {
  1324. //
  1325. // Compute how many bytes we want to throw away
  1326. // from this buffer so we can read in more data.
  1327. // We don't want to throw away all the bytes because
  1328. // the tag we want may span two buffers.
  1329. //
  1330. DWORD cchSkip = cchBuf - cchTag;
  1331. //
  1332. // Advance the file offset.
  1333. //
  1334. iOffset += cchSkip;
  1335. //
  1336. // Reduce the buffer size.
  1337. //
  1338. cchBuf -= cchSkip;
  1339. //
  1340. // Move the kept bytes to the beginning of the buffer.
  1341. //
  1342. MoveMemory(wszBuf, wszBuf + cchSkip, cchBuf*sizeof(wszBuf[0]));
  1343. }
  1344. }
  1345. else
  1346. {
  1347. fDoneReading = TRUE;
  1348. }
  1349. }
  1350. EXITPROC(2, "DS ScanForTag=%d", iRet);
  1351. return iRet;
  1352. }
  1353. int CActiveDesktop::_ScanTagEntriesA(CReadFileObj *pReadFileObj, int iOffsetStart, TAGENTRYA *pte, int cte)
  1354. {
  1355. ENTERPROC(2, "DS ScanTagEntriesA(pReadFileObj=%08X,iOffsetStart=%d,pte=%08X,cte=%d)",
  1356. pReadFileObj, iOffsetStart, pte, cte);
  1357. int iRet = -1;
  1358. int i;
  1359. for (i=0; i<cte; i++,pte++)
  1360. {
  1361. iRet = _ScanForTagA(pReadFileObj, iOffsetStart, pte->pszTag);
  1362. if (iRet != -1)
  1363. {
  1364. if (pte->fSkipPast)
  1365. {
  1366. iRet += lstrlenA(pte->pszTag);
  1367. }
  1368. break;
  1369. }
  1370. }
  1371. EXITPROC(2, "DS ScanTagEntriesA=%d", iRet);
  1372. return iRet;
  1373. }
  1374. int CActiveDesktop::_ScanTagEntriesW(CReadFileObj *pReadFileObj, int iOffsetStart, TAGENTRYW *pte, int cte)
  1375. {
  1376. ENTERPROC(2, "DS ScanTagEntriesW(pReadFileObj=%08X,iOffsetStart=%d,pte=%08X,cte=%d)",
  1377. pReadFileObj, iOffsetStart, pte, cte);
  1378. int iRet = -1;
  1379. int i;
  1380. for (i=0; i<cte; i++,pte++)
  1381. {
  1382. iRet = _ScanForTagW(pReadFileObj, iOffsetStart, pte->pwszTag);
  1383. if (iRet != -1)
  1384. {
  1385. if (pte->fSkipPast)
  1386. {
  1387. iRet += lstrlenW(pte->pwszTag);
  1388. }
  1389. break;
  1390. }
  1391. }
  1392. EXITPROC(2, "DS ScanTagEntriesW=%d", iRet);
  1393. return iRet;
  1394. }
  1395. void CActiveDesktop::_ParseAnsiInputHtmlFile( LPTSTR szSelectedWallpaper, int *piOffsetBase, int *piOffsetComp)
  1396. {
  1397. //
  1398. // Figure out where to insert the base href tag.
  1399. //
  1400. int iOffsetBase = 0, iBaseTagStart;
  1401. BOOL fUseBaseHref;
  1402. LONG lOffsetDueToBOM = 0; //Character Offset due to the Byte Order Mark.
  1403. //1 for UNICODE and 0 for ANSI files.
  1404. // 98/11/11 #248047 vtan: This code looks for a <BASE HREF=...> tag.
  1405. // It used to use a scan for "<BASE" and assume that this was the
  1406. // desired tag. HTML allows a "<BASEFONT>" tag which was being
  1407. // mistaken for a "<BASE HREF=...>" tag. The code now looks for the
  1408. // same string but looks at the character following the "<BASE" to
  1409. // see if it's a white-space character.
  1410. fUseBaseHref = TRUE;
  1411. _pReadFileObjHtmlBkgd->FileGetCurCharOffset(&lOffsetDueToBOM);
  1412. iOffsetBase = (int)lOffsetDueToBOM;
  1413. iBaseTagStart = _ScanForTagA(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, "<BASE");
  1414. if (iBaseTagStart != -1)
  1415. {
  1416. UINT uiCountChars, uiTryToRead;
  1417. char szBaseTagBuffer[6+1]; // allow for "<BASEx" plus a NULL.
  1418. _pReadFileObjHtmlBkgd->FileSeekChars(iBaseTagStart, FILE_BEGIN);
  1419. uiTryToRead = ARRAYSIZE(szBaseTagBuffer) - 1;
  1420. if (SUCCEEDED(_pReadFileObjHtmlBkgd->FileReadCharsA(szBaseTagBuffer, uiTryToRead, &uiCountChars)) && uiCountChars)
  1421. {
  1422. char ch;
  1423. ch = szBaseTagBuffer[5];
  1424. fUseBaseHref = ((ch != ' ') &&
  1425. (ch != '\r') &&
  1426. (ch != '\n') && // this covers the UNIX line break scheme
  1427. (ch != '\t'));
  1428. }
  1429. }
  1430. if (fUseBaseHref)
  1431. {
  1432. TAGENTRYA rgteBase[] = {
  1433. { "<HEAD>", TRUE, },
  1434. { "<BODY", FALSE, },
  1435. { "<HTML>", TRUE, },
  1436. };
  1437. iOffsetBase = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, rgteBase, ARRAYSIZE(rgteBase));
  1438. if (iOffsetBase == -1)
  1439. {
  1440. iOffsetBase = (int)lOffsetDueToBOM;
  1441. }
  1442. }
  1443. //
  1444. // Figure out where to insert the components.
  1445. //
  1446. TAGENTRYA rgteComponents[] = {
  1447. { "</BODY>", FALSE, },
  1448. { "</HTML>", FALSE, },
  1449. };
  1450. int iOffsetComponents = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, iOffsetBase, rgteComponents, ARRAYSIZE(rgteComponents));
  1451. //
  1452. // Write out the initial HTML up to the <HEAD> tag.
  1453. //
  1454. _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, iOffsetBase);
  1455. //
  1456. // Write out the base tag.
  1457. //
  1458. if (fUseBaseHref)
  1459. {
  1460. //BASE tag must point to the base "URL". So, don't strip out the filename.
  1461. _WriteHtmlFromIdF(IDS_BASE_TAG, szSelectedWallpaper);
  1462. }
  1463. // Figure out where to insert the DIV clause
  1464. TAGENTRYA rgteBodyStart[] = {
  1465. { "<BODY", FALSE, },
  1466. };
  1467. int iOffsetBodyStart = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, iOffsetBase, rgteBodyStart, ARRAYSIZE(rgteBodyStart));
  1468. // Write out HTML until after the <BODY ......>
  1469. if (iOffsetBodyStart == -1)
  1470. { // the <BODY> tag is not found, so we need to insert it.
  1471. // Copy over stuff until </HEAD>
  1472. TAGENTRYA rgteHeadEnd[] = {
  1473. { "</HEAD>", TRUE, },
  1474. };
  1475. int iOffsetHeadEnd = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, iOffsetBase, rgteHeadEnd, ARRAYSIZE(rgteHeadEnd));
  1476. if (iOffsetHeadEnd != -1)
  1477. {
  1478. _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetHeadEnd);
  1479. iOffsetBase = iOffsetHeadEnd;
  1480. }
  1481. _WriteHtmlFromIdF(IDS_BODY_CENTER_WP2); // "<BODY>"
  1482. _fNeedBodyEnd = TRUE;
  1483. }
  1484. else
  1485. {
  1486. TAGENTRYA rgteBodyEnd[] = {
  1487. { ">", TRUE, },
  1488. };
  1489. int iOffsetBodyEnd = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, iOffsetBodyStart, rgteBodyEnd, ARRAYSIZE(rgteBodyEnd));
  1490. if (iOffsetBodyEnd == -1)
  1491. { // An error in the HTML.
  1492. iOffsetBodyEnd = iOffsetBodyStart; // FEATURE: We need a better recovery idea.
  1493. }
  1494. _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetBodyEnd);
  1495. iOffsetBase = iOffsetBodyEnd;
  1496. }
  1497. *piOffsetBase = iOffsetBase;
  1498. *piOffsetComp = iOffsetComponents;
  1499. }
  1500. void CActiveDesktop::_GenerateHtmlHeader(void)
  1501. {
  1502. ENTERPROC(2, "DS GenerateHtmlHeader()");
  1503. EnumMonitorsArea ema;
  1504. GetMonitorSettings(&ema);
  1505. RECT rcViewAreas[LV_MAX_WORKAREAS]; // WorkArea minus toolbar/tray areas
  1506. int nViewAreas = ARRAYSIZE(rcViewAreas);
  1507. // Get the ViewAreas
  1508. if (!GetViewAreas(rcViewAreas, &nViewAreas))
  1509. {
  1510. nViewAreas = 0;
  1511. }
  1512. //Assume that the final Deskstat.htt that we generate is going to be in UNICODE.
  1513. //This will change to ANSI only if the background html wallpaper is ANSI (determined later)
  1514. _iDestFileCharset = UNICODE_HTML_CHARSET;
  1515. //
  1516. // Write out the background and color.
  1517. //
  1518. TCHAR szSelectedWallpaper[INTERNET_MAX_URL_LENGTH];
  1519. // If the wallpaper does not have a directory specified (this may happen if other apps. change this value),
  1520. // we have to figure it out.
  1521. if (!GetWallpaperWithPath(_szSelectedWallpaper, szSelectedWallpaper, ARRAYSIZE(szSelectedWallpaper)))
  1522. {
  1523. return; // gross, but probably cleanest way
  1524. }
  1525. BOOL fValidWallpaper = GetFileAttributes(szSelectedWallpaper) != 0xFFFFFFFF;
  1526. if (_fSingleItem || IsWallpaperPicture(szSelectedWallpaper) || !fValidWallpaper)
  1527. {
  1528. //
  1529. // Write the BOM for UNICODE
  1530. //
  1531. if (_hFileHtml)
  1532. {
  1533. DWORD cbWritten;
  1534. WriteFile(_hFileHtml, (LPCSTR)&wUnicodeBOM, sizeof(wUnicodeBOM), &cbWritten, NULL);
  1535. }
  1536. // To account for the vagaries of the desktop browser (it's TopLeft starts from the TopLeft
  1537. // of the Desktop ViewArea instead of the TopLeft of the monitor, as might be expected)
  1538. // which happens only in the case of one active monitor systems, we add the width of the
  1539. // tray/toolbars to the co-ordinates of the DIV section of each monitor's wallpaper.
  1540. int iLeft, iTop;
  1541. if (nViewAreas == 1)
  1542. {
  1543. iLeft = rcViewAreas[0].left - ema.rcVirtualMonitor.left;
  1544. iTop = rcViewAreas[0].top - ema.rcVirtualMonitor.top;
  1545. }
  1546. else
  1547. {
  1548. iLeft = 0;
  1549. iTop = 0;
  1550. }
  1551. //
  1552. // Write out the standard header.
  1553. //
  1554. UINT i;
  1555. for (i=IDS_COMMENT_BEGIN; i<IDS_BODY_BEGIN; i++)
  1556. {
  1557. _WriteHtmlFromIdF(i);
  1558. }
  1559. //
  1560. // Write out the body tag, with background bitmap.
  1561. //
  1562. DWORD rgbDesk;
  1563. rgbDesk = GetSysColor(COLOR_DESKTOP);
  1564. TCHAR szBitmapFile[MAX_PATH];
  1565. if (FAILED(GetPerUserFileName(szBitmapFile, ARRAYSIZE(szBitmapFile), PATTERN_FILENAME)))
  1566. {
  1567. szBitmapFile[0] = 0;
  1568. }
  1569. if (!_fSingleItem && _szSelectedWallpaper[0] && fValidWallpaper)
  1570. {
  1571. TCHAR szWallpaperUrl[INTERNET_MAX_URL_LENGTH];
  1572. DWORD cch = ARRAYSIZE(szWallpaperUrl);
  1573. UrlCreateFromPath(szSelectedWallpaper, szWallpaperUrl, &cch, URL_INTERNAL_PATH);
  1574. switch (_wpo.dwStyle)
  1575. {
  1576. case WPSTYLE_TILE:
  1577. //
  1578. // Ignore the pattern, tile the wallpaper as background.
  1579. //
  1580. _WriteHtmlFromIdF(IDS_BODY_BEGIN2, szWallpaperUrl, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1581. break;
  1582. case WPSTYLE_CENTER:
  1583. if (IsValidPattern(_szSelectedPattern))
  1584. {
  1585. //
  1586. // Tile the pattern as the main background.
  1587. //
  1588. _WriteHtmlFromIdF(IDS_BODY_BEGIN2, szBitmapFile, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1589. if (_fBackgroundHtml) // We are generating the HTML for preview
  1590. {
  1591. _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP, szWallpaperUrl);
  1592. }
  1593. else
  1594. {
  1595. //
  1596. // Write out a DIV section for a centered, untiled wallpaper.
  1597. //
  1598. // write it out for each monitor.
  1599. for(int i = 0; i < ema.iMonitors; i++)
  1600. {
  1601. _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP2,
  1602. ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft,
  1603. ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop,
  1604. ema.rcMonitor[i].right - ema.rcMonitor[i].left,
  1605. ema.rcMonitor[i].bottom - ema.rcMonitor[i].top,
  1606. szWallpaperUrl);
  1607. }
  1608. }
  1609. }
  1610. else
  1611. {
  1612. //
  1613. // Write out a non-tiled, centered wallpaper as background.
  1614. //
  1615. if (_fBackgroundHtml) // We are generating the HTML for preview
  1616. {
  1617. _WriteHtmlFromIdF(IDS_BODY_CENTER_WP, szWallpaperUrl, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1618. }
  1619. else
  1620. {
  1621. _WriteHtmlFromIdF(IDS_BODY_CENTER_WP2, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1622. // write it out for each monitor.
  1623. for(int i = 0; i < ema.iMonitors; i++)
  1624. {
  1625. _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP2,
  1626. ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft,
  1627. ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop,
  1628. ema.rcMonitor[i].right - ema.rcMonitor[i].left,
  1629. ema.rcMonitor[i].bottom - ema.rcMonitor[i].top,
  1630. szWallpaperUrl);
  1631. }
  1632. }
  1633. }
  1634. break;
  1635. case WPSTYLE_STRETCH:
  1636. //
  1637. // Ignore the pattern, create a DIV section of the wallpaper
  1638. // stretched to 100% of the screen.
  1639. //
  1640. _WriteHtmlFromIdF(IDS_BODY_BEGIN2, c_szNULL, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1641. if (_fBackgroundHtml) // We are generating the HTML for preview
  1642. {
  1643. _WriteHtmlFromIdF(IDS_STRETCH_WALLPAPER, szWallpaperUrl);
  1644. }
  1645. else
  1646. {
  1647. // stretch it for each monitor.
  1648. for(int i = 0; i < ema.iMonitors; i++)
  1649. {
  1650. _WriteHtmlFromIdF(IDS_DIV_START3, ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft,
  1651. ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop,
  1652. ema.rcMonitor[i].right - ema.rcMonitor[i].left,
  1653. ema.rcMonitor[i].bottom - ema.rcMonitor[i].top);
  1654. _WriteHtmlFromIdF(IDS_STRETCH_WALLPAPER, szWallpaperUrl);
  1655. _WriteHtmlFromId(IDS_DIV_END);
  1656. }
  1657. }
  1658. break;
  1659. }
  1660. }
  1661. else
  1662. {
  1663. //
  1664. // Ignore the wallpaper, generate either a tiled pattern
  1665. // or solid color background.
  1666. //
  1667. _WriteHtmlFromIdF(IDS_BODY_BEGIN2, !_fSingleItem && IsValidPattern(_szSelectedPattern) ? szBitmapFile : c_szNULL, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk));
  1668. }
  1669. }
  1670. else
  1671. {
  1672. if ((_pReadFileObjHtmlBkgd = new CReadFileObj(szSelectedWallpaper)) &&
  1673. (_pReadFileObjHtmlBkgd->_hFile != INVALID_HANDLE_VALUE))
  1674. {
  1675. //The final Desktop.htt will be in ANSI only if the source html file is also in ansi.
  1676. //So, get the type from the selected wallpaper object.
  1677. _iDestFileCharset = _pReadFileObjHtmlBkgd->_iCharset;
  1678. //
  1679. // Write the BOM for UNICODE
  1680. //
  1681. if (_hFileHtml && (_iDestFileCharset == UNICODE_HTML_CHARSET))
  1682. {
  1683. DWORD cbWritten;
  1684. WriteFile(_hFileHtml, (LPCSTR)&wUnicodeBOM, sizeof(wUnicodeBOM), &cbWritten, NULL);
  1685. }
  1686. //
  1687. // Figure out where to insert the base href tag.
  1688. //
  1689. int iOffsetBase = 0;
  1690. int iOffsetComponents;
  1691. // 98/11/11 #248047 vtan: This code looks for a <BASE HREF=...> tag.
  1692. // It used to use a scan for "<BASE" and assume that this was the
  1693. // desired tag. HTML allows a "<BASEFONT>" tag which was being
  1694. // mistaken for a "<BASE HREF=...>" tag. The code now looks for the
  1695. // same string but looks at the character following the "<BASE" to
  1696. // see if it's a white-space character.
  1697. if (_iDestFileCharset == ANSI_HTML_CHARSET)
  1698. {
  1699. //The following function parses the ANSI input html file and finds various offsets
  1700. _ParseAnsiInputHtmlFile(szSelectedWallpaper, &iOffsetBase, &iOffsetComponents);
  1701. }
  1702. else
  1703. {
  1704. //The following code parses the UNICODE input html wallpaper file.
  1705. int iBaseTagStart;
  1706. BOOL fUseBaseHref;
  1707. LONG lOffsetDueToBOM = 0; //Character Offset due to the Byte Order Mark.
  1708. //1 for UNICODE and 0 for ANSI files.
  1709. fUseBaseHref = TRUE;
  1710. _pReadFileObjHtmlBkgd->FileGetCurCharOffset(&lOffsetDueToBOM);
  1711. iOffsetBase = (int)lOffsetDueToBOM;
  1712. iBaseTagStart = _ScanForTagW(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, L"<BASE");
  1713. if (iBaseTagStart != -1)
  1714. {
  1715. UINT uiCountChars, uiTryToRead;
  1716. WCHAR wszBaseTagBuffer[6+1]; // allow for "<BASEx" plus a NULL.
  1717. _pReadFileObjHtmlBkgd->FileSeekChars(iBaseTagStart, FILE_BEGIN);
  1718. uiTryToRead = ARRAYSIZE(wszBaseTagBuffer) - 1;
  1719. if (SUCCEEDED(_pReadFileObjHtmlBkgd->FileReadCharsW(wszBaseTagBuffer, uiTryToRead, &uiCountChars)) && uiCountChars)
  1720. {
  1721. WCHAR wc;
  1722. wc = wszBaseTagBuffer[5];
  1723. fUseBaseHref = ((wc != L' ') &&
  1724. (wc != L'\r') &&
  1725. (wc != L'\n') && // this covers the UNIX line break scheme
  1726. (wc != L'\t'));
  1727. }
  1728. }
  1729. if (fUseBaseHref)
  1730. {
  1731. TAGENTRYW rgteBase[] = {
  1732. { L"<HEAD>", TRUE, },
  1733. { L"<BODY", FALSE, },
  1734. { L"<HTML>", TRUE, },
  1735. };
  1736. iOffsetBase = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, rgteBase, ARRAYSIZE(rgteBase));
  1737. if (iOffsetBase == -1)
  1738. {
  1739. iOffsetBase = (int)lOffsetDueToBOM;
  1740. }
  1741. }
  1742. //
  1743. // Figure out where to insert the components.
  1744. //
  1745. TAGENTRYW rgteComponents[] = {
  1746. { L"</BODY>", FALSE, },
  1747. { L"</HTML>", FALSE, },
  1748. };
  1749. iOffsetComponents = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, iOffsetBase, rgteComponents, ARRAYSIZE(rgteComponents));
  1750. //
  1751. // Write out the initial HTML up to the <HEAD> tag.
  1752. //
  1753. _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, iOffsetBase);
  1754. //
  1755. // Write out the base tag.
  1756. //
  1757. if (fUseBaseHref)
  1758. {
  1759. //BASE tag must point to the base "URL". So, don't strip out the filename.
  1760. _WriteHtmlFromIdF(IDS_BASE_TAG, szSelectedWallpaper);
  1761. }
  1762. // Figure out where to insert the DIV clause
  1763. TAGENTRYW rgteBodyStart[] = {
  1764. { L"<BODY", FALSE, },
  1765. };
  1766. int iOffsetBodyStart = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, iOffsetBase, rgteBodyStart, ARRAYSIZE(rgteBodyStart));
  1767. // Write out HTML until after the <BODY ......>
  1768. if (iOffsetBodyStart == -1)
  1769. { // the <BODY> tag is not found, so we need to insert it.
  1770. // Copy over stuff until </HEAD>
  1771. TAGENTRYW rgteHeadEnd[] = {
  1772. { L"</HEAD>", TRUE, },
  1773. };
  1774. int iOffsetHeadEnd = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, iOffsetBase, rgteHeadEnd, ARRAYSIZE(rgteHeadEnd));
  1775. if (iOffsetHeadEnd != -1)
  1776. {
  1777. _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetHeadEnd);
  1778. iOffsetBase = iOffsetHeadEnd;
  1779. }
  1780. _WriteHtmlFromIdF(IDS_BODY_CENTER_WP2); // "<BODY>"
  1781. _fNeedBodyEnd = TRUE;
  1782. }
  1783. else
  1784. {
  1785. TAGENTRYW rgteBodyEnd[] = {
  1786. { L">", TRUE, },
  1787. };
  1788. int iOffsetBodyEnd = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, iOffsetBodyStart, rgteBodyEnd, ARRAYSIZE(rgteBodyEnd));
  1789. if (iOffsetBodyEnd == -1)
  1790. { // An error in the HTML.
  1791. iOffsetBodyEnd = iOffsetBodyStart; // FEATURE: We need a better recovery idea.
  1792. }
  1793. _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetBodyEnd);
  1794. iOffsetBase = iOffsetBodyEnd;
  1795. }
  1796. }
  1797. // Insert the DIV clause
  1798. if (ema.iMonitors > 1)
  1799. {
  1800. int iIndexPrimaryMonitor;
  1801. HMONITOR hMonitorPrimary;
  1802. MONITORINFO monitorInfo;
  1803. // 99/03/23 #275429 vtan: We used GetViewAreas() to fill in rcViewAreas above.
  1804. // The code here used to assume that [0] ALWAYS referred to the primary monitor.
  1805. // This isn't the case if the monitor settings are changed without a restart.
  1806. // In order to compensate for this and always render the wallpaper into the
  1807. // primary monitor, a search is performed to find a (left, top) that matches
  1808. // one of the work areas and this is used as the primary monitor. If none can
  1809. // be found then default to the old algorithm.
  1810. hMonitorPrimary = GetPrimaryMonitor();
  1811. monitorInfo.cbSize = sizeof(monitorInfo);
  1812. TBOOL(GetMonitorInfo(hMonitorPrimary, &monitorInfo));
  1813. iIndexPrimaryMonitor = -1;
  1814. for (int i = 0; (iIndexPrimaryMonitor < 0) && (i < nViewAreas); ++i)
  1815. {
  1816. if ((monitorInfo.rcWork.left == rcViewAreas[i].left) && (monitorInfo.rcWork.top == rcViewAreas[i].top))
  1817. {
  1818. iIndexPrimaryMonitor = i;
  1819. }
  1820. }
  1821. if (iIndexPrimaryMonitor < 0)
  1822. iIndexPrimaryMonitor = 0;
  1823. if ((nViewAreas <= 0) || (rcViewAreas[iIndexPrimaryMonitor].right == rcViewAreas[iIndexPrimaryMonitor].left))
  1824. // The second case could occur on bootup
  1825. {
  1826. // Some error occured when getting the ViewAreas. Recover from the error by using the workarea.
  1827. // Get the workarea of the primary monitor, since HTML wallpapers are displayed only there.
  1828. GetMonitorWorkArea(hMonitorPrimary, &rcViewAreas[iIndexPrimaryMonitor]);
  1829. }
  1830. _WriteHtmlFromIdF(IDS_DIV_START3,
  1831. rcViewAreas[iIndexPrimaryMonitor].left - ema.rcVirtualMonitor.left,
  1832. rcViewAreas[iIndexPrimaryMonitor].top - ema.rcVirtualMonitor.top,
  1833. rcViewAreas[iIndexPrimaryMonitor].right - rcViewAreas[iIndexPrimaryMonitor].left,
  1834. rcViewAreas[iIndexPrimaryMonitor].bottom - rcViewAreas[iIndexPrimaryMonitor].top);
  1835. }
  1836. //
  1837. // Write out HTML from after <HEAD> tag to just before </BODY> tag.
  1838. //
  1839. _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetComponents);
  1840. if (ema.iMonitors > 1)
  1841. {
  1842. _WriteHtmlFromId(IDS_DIV_END);
  1843. }
  1844. }
  1845. else
  1846. {
  1847. if (_pReadFileObjHtmlBkgd)
  1848. delete _pReadFileObjHtmlBkgd;
  1849. _pReadFileObjHtmlBkgd = NULL;
  1850. }
  1851. }
  1852. EXITPROC(2, "DS GenerateHtmlHeader!");
  1853. }
  1854. void CActiveDesktop::_WriteResizeable(COMPONENTA *pcomp)
  1855. {
  1856. TCHAR szResizeable[3];
  1857. //If Resize is set, then the comp is resizeable in both X and Y directions!
  1858. if (pcomp->cpPos.fCanResize || (pcomp->cpPos.fCanResizeX && pcomp->cpPos.fCanResizeY))
  1859. {
  1860. szResizeable[0] = TEXT('X');
  1861. szResizeable[1] = TEXT('Y');
  1862. szResizeable[2] = TEXT('\0');
  1863. }
  1864. else if (pcomp->cpPos.fCanResizeX)
  1865. {
  1866. szResizeable[0] = TEXT('X');
  1867. szResizeable[1] = TEXT('\0');
  1868. }
  1869. else if (pcomp->cpPos.fCanResizeY)
  1870. {
  1871. szResizeable[0] = TEXT('Y');
  1872. szResizeable[1] = TEXT('\0');
  1873. }
  1874. _WriteHtmlFromIdF(IDS_RESIZEABLE, szResizeable);
  1875. }
  1876. void CActiveDesktop::_WriteHtmlW(LPCWSTR wcBuf, UINT cchToWrite, UINT *pcchWritten)
  1877. {
  1878. ULONG cchWritten = 0;
  1879. UINT uiSize;
  1880. if (_pStream)
  1881. {
  1882. uiSize = sizeof(WCHAR);
  1883. _pStream->Write((LPVOID)wcBuf, cchToWrite * uiSize, &cchWritten);
  1884. }
  1885. else
  1886. {
  1887. ASSERT(_hFileHtml);
  1888. uiSize = (_iDestFileCharset == ANSI_HTML_CHARSET) ? sizeof(char) : sizeof(WCHAR);
  1889. WriteFile(_hFileHtml, (LPCVOID)wcBuf, cchToWrite * uiSize, &cchWritten, NULL);
  1890. }
  1891. *pcchWritten = (UINT)(cchWritten/uiSize); //Convert to number of chars.
  1892. }
  1893. void CActiveDesktop::_GenerateHtmlPicture(COMPONENTA *pcomp)
  1894. {
  1895. ENTERPROC(2, "DS GenerateHtmlPicture(pcomp=%08X)");
  1896. //
  1897. // Write out the image src HTML.
  1898. //
  1899. TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  1900. DWORD cch = ARRAYSIZE(szUrl);
  1901. HRESULT hr = UrlCreateFromPath(pcomp->szSource, szUrl, &cch, 0);
  1902. if (FAILED(hr))
  1903. {
  1904. hr = StringCchCopy(szUrl, ARRAYSIZE(szUrl), pcomp->szSource);
  1905. }
  1906. if (SUCCEEDED(hr))
  1907. {
  1908. _WriteHtmlFromIdF(IDS_IMAGE_BEGIN2, pcomp->dwID, szUrl);
  1909. //
  1910. // Write out whether this image is resizeable or not!
  1911. //
  1912. _WriteResizeable(pcomp);
  1913. //
  1914. // Write out the URL that must be used for subscription purposes.
  1915. //
  1916. _WriteHtmlFromIdF(IDS_SUBSCRIBEDURL, pcomp->szSubscribedURL);
  1917. //
  1918. // Write out the image location HTML.
  1919. //
  1920. if ((pcomp->cpPos.dwWidth == COMPONENT_DEFAULT_WIDTH) &&
  1921. (pcomp->cpPos.dwHeight == COMPONENT_DEFAULT_HEIGHT))
  1922. {
  1923. _WriteHtmlFromIdF(IDS_IMAGE_LOCATION, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.izIndex);
  1924. }
  1925. else
  1926. {
  1927. _WriteHtmlFromIdF(IDS_IMAGE_SIZE, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop,
  1928. pcomp->cpPos.dwWidth, pcomp->cpPos.dwHeight, pcomp->cpPos.izIndex);
  1929. }
  1930. }
  1931. EXITPROC(2, "DS GenerateHtmlPicture!");
  1932. }
  1933. void CActiveDesktop::_GenerateHtmlDoc(COMPONENTA *pcomp)
  1934. {
  1935. ENTERPROC(2, "DS GenerateHtmlDoc(pcomp=%08X)");
  1936. TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  1937. DWORD dwSize = ARRAYSIZE(szUrl);
  1938. LPTSTR lpszUrl = szUrl;
  1939. if (FAILED(UrlCreateFromPath(pcomp->szSource, szUrl, &dwSize, 0)))
  1940. lpszUrl = pcomp->szSource;
  1941. //
  1942. // Write out the DIV header HTML.
  1943. //
  1944. _WriteHtmlFromIdF(IDS_DIV_START2, pcomp->dwID, lpszUrl);
  1945. //
  1946. // Write out whether this component is resizeable or not!
  1947. //
  1948. _WriteResizeable(pcomp);
  1949. //
  1950. // Write out the DIV location HTML.
  1951. //
  1952. _WriteHtmlFromIdF(IDS_DIV_SIZE, pcomp->cpPos.dwHeight, _fSingleItem ? 0 : pcomp->cpPos.iLeft,
  1953. _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.dwWidth, pcomp->cpPos.izIndex);
  1954. //
  1955. // Extract the doc contents directly into the HTML.
  1956. //
  1957. _WriteHtmlFromFile(pcomp->szSource);
  1958. //
  1959. // Close the DIV section.
  1960. //
  1961. _WriteHtmlFromId(IDS_DIV_END);
  1962. EXITPROC(2, "DS GenerateHtmlDoc!");
  1963. }
  1964. void CActiveDesktop::_GenerateHtmlSite(COMPONENTA *pcomp)
  1965. {
  1966. ENTERPROC(2, "DS GenerateHtmlSite(pcomp=%08X)");
  1967. //
  1968. // Write out the frame src HTML.
  1969. //
  1970. TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  1971. DWORD cch=ARRAYSIZE(szUrl);
  1972. if (FAILED(UrlCreateFromPath(pcomp->szSource, szUrl, &cch, 0)))
  1973. {
  1974. if (FAILED(StringCchCopy(szUrl, ARRAYSIZE(szUrl), pcomp->szSource)))
  1975. {
  1976. return;
  1977. }
  1978. }
  1979. DWORD currentURLLength, maximumURLLength;
  1980. LPTSTR pszURL = NULL;
  1981. TCHAR szFormatBuffer[0x0100];
  1982. // 98/09/29 #211384 vtan: There is a limitation in wvsprintf.
  1983. // It only allows 2048 bytes in its buffer. If the URL is
  1984. // longer than 1024 characters less the IDS_IFRAME_BEGIN2
  1985. // string length less the component ID less "scrolling=no"
  1986. // if the component cannot be scrolled then the URL string
  1987. // will not be correctly inserted into the IDS_IFRAME_BEGIN2
  1988. // string and there will be a missing end-quote and trident
  1989. // will fail to render desktop.htt correctly.
  1990. // To correct against this the followING limits the length of
  1991. // the URL to this maximum and truncates any characters
  1992. // beyond the limit so that the IDS_IFRAME_BEGIN2 string
  1993. // contains its end-quote and trident does not barf.
  1994. // The above condition is a boundary condition and this
  1995. // check is quick so that the calculations that follow do
  1996. // not have to be executed repeatedly.
  1997. currentURLLength = lstrlen(szUrl);
  1998. if (currentURLLength > 768) // a hard-coded limit
  1999. {
  2000. maximumURLLength = 1024; // wvsprintf limit
  2001. LoadString(HINST_THISDLL, IDS_IFRAME_BEGIN2, szFormatBuffer, ARRAYSIZE(szFormatBuffer));
  2002. maximumURLLength -= lstrlen(szFormatBuffer); // IDS_IFRAME_BEGIN2
  2003. maximumURLLength -= 16; // pcomp->dwID
  2004. maximumURLLength -= lstrlen(TEXT("scrolling=no")); // pcomp->fNoScroll
  2005. if (currentURLLength > maximumURLLength)
  2006. szUrl[maximumURLLength] = static_cast<TCHAR>('\0');
  2007. }
  2008. _WriteHtmlFromIdF(IDS_IFRAME_BEGIN2, pcomp->dwID, szUrl, pcomp->fNoScroll ? TEXT("scrolling=no") : c_szNULL);
  2009. //
  2010. // Write out whether this Component is resizeable or not!
  2011. //
  2012. _WriteResizeable(pcomp);
  2013. // 98/09/29 #211384 vtan: See above.
  2014. currentURLLength = lstrlen(pcomp->szSubscribedURL);
  2015. if (currentURLLength > 768)
  2016. {
  2017. if (SUCCEEDED(StringCchCopy(szUrl, ARRAYSIZE(szUrl), pcomp->szSubscribedURL)))
  2018. {
  2019. maximumURLLength = 1024;
  2020. LoadString(HINST_THISDLL, IDS_SUBSCRIBEDURL, szFormatBuffer, ARRAYSIZE(szFormatBuffer));
  2021. maximumURLLength -= lstrlen(szFormatBuffer); // IDS_SUBSCRIBEDURL
  2022. if (currentURLLength > maximumURLLength)
  2023. szUrl[maximumURLLength] = static_cast<TCHAR>('\0');
  2024. pszURL = szUrl;
  2025. }
  2026. }
  2027. else
  2028. {
  2029. pszURL = pcomp->szSubscribedURL;
  2030. }
  2031. if (pszURL)
  2032. {
  2033. //
  2034. // Write out the URL that must be used for subscription purposes.
  2035. //
  2036. _WriteHtmlFromIdF(IDS_SUBSCRIBEDURL, pszURL);
  2037. //
  2038. // Write out the frame location HTML.
  2039. //
  2040. _WriteHtmlFromIdF(IDS_IFRAME_SIZE, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop,
  2041. pcomp->cpPos.dwWidth, pcomp->cpPos.dwHeight, pcomp->cpPos.izIndex);
  2042. }
  2043. EXITPROC(2, "DS GenerateHtmlSite!");
  2044. }
  2045. void CActiveDesktop::_GenerateHtmlControl(COMPONENTA *pcomp)
  2046. {
  2047. ENTERPROC(2, "DS GenerateHtmlControl(pcomp=%08X)");
  2048. ASSERT(pcomp);
  2049. // Did the Administrator restrict "Channel UI"?
  2050. if (SHRestricted2W(REST_NoChannelUI, NULL, 0))
  2051. {
  2052. TCHAR szChannelOCGUID[GUIDSTR_MAX];
  2053. SHStringFromGUID(CLSID_ChannelOC, szChannelOCGUID, ARRAYSIZE(szChannelOCGUID));
  2054. if (!StrCmpNI(pcomp->szSource, &(szChannelOCGUID[1]), lstrlen(pcomp->szSource)-3))
  2055. {
  2056. // Yes, so we need to hide the Channel Desktop Component.
  2057. // Return here before we generate it.
  2058. return;
  2059. }
  2060. }
  2061. //
  2062. // Write out the control HTML.
  2063. //
  2064. // First the control header
  2065. _WriteHtmlFromIdF(IDS_CONTROL_1, pcomp->dwID);
  2066. // then the size
  2067. _WriteHtmlFromIdF(IDS_CONTROL_2, pcomp->cpPos.dwHeight, _fSingleItem ? 0 : pcomp->cpPos.iLeft,
  2068. _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.dwWidth, pcomp->cpPos.izIndex);
  2069. //
  2070. // Write out whether this Control is resizeable or not!
  2071. //
  2072. _WriteResizeable(pcomp);
  2073. // Finally the rest of the control
  2074. _WriteHtmlFromIdF(IDS_CONTROL_3, pcomp->szSource);
  2075. EXITPROC(2, "DS GenerateHtmlControl!");
  2076. }
  2077. void CActiveDesktop::_GenerateHtmlComponent(COMPONENTA *pcomp)
  2078. {
  2079. ENTERPROC(2, "DS GenerateHtmlComponent(pcomp=%08X)");
  2080. switch(pcomp->iComponentType)
  2081. {
  2082. case COMP_TYPE_PICTURE:
  2083. _GenerateHtmlPicture(pcomp);
  2084. break;
  2085. case COMP_TYPE_HTMLDOC:
  2086. _GenerateHtmlDoc(pcomp);
  2087. break;
  2088. case COMP_TYPE_WEBSITE:
  2089. _GenerateHtmlSite(pcomp);
  2090. break;
  2091. case COMP_TYPE_CONTROL:
  2092. _GenerateHtmlControl(pcomp);
  2093. break;
  2094. }
  2095. EXITPROC(2, "DS GenerateHtmlComponent!");
  2096. }
  2097. void CActiveDesktop::_GenerateHtmlFooter(void)
  2098. {
  2099. ENTERPROC(2, "DS GenerateHtmlFooter()");
  2100. //
  2101. // Write out the deskmovr object.
  2102. //
  2103. if (!_fNoDeskMovr)
  2104. {
  2105. TCHAR szDeskMovrFile[MAX_PATH];
  2106. if (GetWindowsDirectory(szDeskMovrFile, ARRAYSIZE(szDeskMovrFile)) &&
  2107. PathAppend(szDeskMovrFile, DESKMOVR_FILENAME))
  2108. {
  2109. _WriteHtmlFromFile(szDeskMovrFile);
  2110. }
  2111. }
  2112. //
  2113. // Write out the concluding HTML tags.
  2114. //
  2115. if (_pReadFileObjHtmlBkgd)
  2116. {
  2117. if (_fNeedBodyEnd)
  2118. { // We had introduced the <BODY> tag by ourselves.
  2119. _WriteHtmlFromId(IDS_BODY_END2);
  2120. _fNeedBodyEnd = FALSE;
  2121. }
  2122. _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, -1, -1);
  2123. delete _pReadFileObjHtmlBkgd; //Close the file and cleanup!
  2124. _pReadFileObjHtmlBkgd = NULL;
  2125. }
  2126. else
  2127. {
  2128. _WriteHtmlFromId(IDS_BODY_END);
  2129. }
  2130. EXITPROC(2, "DS GenerateHtmlFooter!");
  2131. }
  2132. void CActiveDesktop::_GenerateHtml(void)
  2133. {
  2134. ENTERPROC(2, "DS GenerateHtml()");
  2135. TCHAR szHtmlFile[MAX_PATH];
  2136. //
  2137. // Compute the filename.
  2138. //
  2139. szHtmlFile[0] = TEXT('\0');
  2140. if (SUCCEEDED(GetPerUserFileName(szHtmlFile, ARRAYSIZE(szHtmlFile), DESKTOPHTML_FILENAME)))
  2141. {
  2142. // Recreate the file.
  2143. _hFileHtml = CreateFile(szHtmlFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  2144. FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL);
  2145. if (_hFileHtml != INVALID_HANDLE_VALUE)
  2146. {
  2147. _GenerateHtmlHeader();
  2148. if (_co.fEnableComponents && _hdsaComponent && DSA_GetItemCount(_hdsaComponent) &&
  2149. !SHRestricted(REST_NODESKCOMP))
  2150. {
  2151. int i;
  2152. for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  2153. {
  2154. COMPONENTA comp;
  2155. comp.dwSize = sizeof(COMPONENTA);
  2156. if ((DSA_GetItem(_hdsaComponent, i, &comp) != -1) && (comp.fChecked))
  2157. {
  2158. _GenerateHtmlComponent(&comp);
  2159. }
  2160. }
  2161. }
  2162. _GenerateHtmlFooter();
  2163. CloseHandle(_hFileHtml);
  2164. SetDesktopFlags(COMPONENTS_DIRTY, 0);
  2165. }
  2166. else
  2167. {
  2168. // 99/05/19 #340772 vtan: If unable to open desktop.htt it's probably
  2169. // in use by another process or task (perhaps trident is trying to
  2170. // render it). In this case mark it dirty so that it will get recreated
  2171. // - yet again but this time with more current data.
  2172. SetDesktopFlags(COMPONENTS_DIRTY, COMPONENTS_DIRTY);
  2173. }
  2174. }
  2175. EXITPROC(2, "DS GenerateHtml!");
  2176. }
  2177. HRESULT CActiveDesktop::GenerateDesktopItemHtml(LPCWSTR pwszFileName, COMPONENT *pcomp, DWORD dwReserved)
  2178. {
  2179. HRESULT hres = E_FAIL;
  2180. ENTERPROC(2, "DS GenerateComponentHtml(pcomp=%08X)", pcomp);
  2181. //Check for the input parameters
  2182. if (!pwszFileName || (pcomp && (pcomp->dwSize != sizeof(*pcomp)) && (pcomp->dwSize != sizeof(IE4COMPONENT))))
  2183. return E_INVALIDARG;
  2184. ASSERT(!dwReserved); // These should be 0
  2185. //
  2186. // Create the file.
  2187. //
  2188. _hFileHtml = CreateFile(pwszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS,
  2189. FILE_ATTRIBUTE_NORMAL, NULL);
  2190. if (_hFileHtml != INVALID_HANDLE_VALUE)
  2191. {
  2192. _fNoDeskMovr = TRUE;
  2193. _fBackgroundHtml = TRUE;
  2194. //Check if we need to add a component
  2195. if (pcomp)
  2196. {
  2197. COMPONENTA CompA;
  2198. CompA.dwSize = sizeof(CompA);
  2199. WideCompToMultiComp(pcomp, &CompA);
  2200. _fSingleItem = TRUE;
  2201. _GenerateHtmlHeader();
  2202. _GenerateHtmlComponent(&CompA);
  2203. _GenerateHtmlFooter();
  2204. _fSingleItem = FALSE;
  2205. }
  2206. else
  2207. {
  2208. //generate just the header and the footer with proper
  2209. // wallpaper and pattern info!
  2210. _GenerateHtmlHeader();
  2211. _GenerateHtmlFooter();
  2212. }
  2213. _fBackgroundHtml = FALSE;
  2214. _fNoDeskMovr = FALSE;
  2215. CloseHandle(_hFileHtml);
  2216. hres = S_OK;
  2217. }
  2218. _hFileHtml = NULL;
  2219. EXITPROC(2, "DS GenerateComponentHtml=%d", hres);
  2220. return hres;
  2221. }
  2222. //
  2223. // AddUrl
  2224. //
  2225. //
  2226. HRESULT CActiveDesktop::AddUrl(HWND hwnd, LPCWSTR pszSourceW, LPCOMPONENT pcomp, DWORD dwFlags)
  2227. {
  2228. LPTSTR pszExt;
  2229. HRESULT fOkay = TRUE;
  2230. BOOL fExtIsCdf,fPathIsUrl;
  2231. BOOL fSubscribed = FALSE;
  2232. COMPONENT compLocal;
  2233. COMPONENTA compA;
  2234. TCHAR szSource[INTERNET_MAX_URL_LENGTH];
  2235. // 98/08/28 vtan #202777: The following if statement sanitizes parameters
  2236. // passed to AddUrl(). The statements following the "||" are executed
  2237. // despite the for pcomp against NULL. This causes an access violation
  2238. // and an exception to be thrown.
  2239. #if 0
  2240. //Check for the input parameters.
  2241. if (!pszSourceW || (pcomp &&
  2242. ((pcomp->dwSize != sizeof(*pcomp)) && (pcomp->dwSize != sizeof(IE4COMPONENT))) ||
  2243. ((pcomp->dwSize == sizeof(*pcomp)) && !VALIDATESTATE(pcomp->dwCurItemState))))
  2244. return E_INVALIDARG;
  2245. #else
  2246. // The following performs the same comparison but is spread into three
  2247. // separate comparisons. As performance is not a critical issue here
  2248. // but correctness is this makes the tests clear and understandable.
  2249. // The invalid conditions are described.
  2250. // Validate input parameters. Invalid parameters are:
  2251. // 1) NULL pszSourceW
  2252. // 2) pcomp->dwSize for a COMPONENT struct but invalid pcomp->dwCurItemState
  2253. // 3) pcomp->dwSize is not for a COMPONENT struct nor for a IE4COMPONENT struct
  2254. if (pszSourceW == NULL)
  2255. return(E_INVALIDARG);
  2256. if (pcomp != NULL)
  2257. {
  2258. if ((pcomp->dwSize == sizeof(*pcomp)) && !VALIDATESTATE(pcomp->dwCurItemState))
  2259. return(E_INVALIDARG);
  2260. if ((pcomp->dwSize != sizeof(*pcomp)) && (pcomp->dwSize != sizeof(IE4COMPONENT)))
  2261. return(E_INVALIDARG);
  2262. }
  2263. #endif
  2264. // Catch folks that call our API's to add components and prevent them from doing
  2265. // so if the restriction is in place.
  2266. if (SHIsRestricted(NULL, REST_NOADDDESKCOMP))
  2267. return E_ACCESSDENIED;
  2268. if (!pcomp)
  2269. {
  2270. pcomp = &compLocal;
  2271. pcomp->dwSize = sizeof(compLocal);
  2272. pcomp->dwCurItemState = IS_NORMAL;
  2273. }
  2274. // Attempt to come up with a reasonable window handle if none is passed in. ParseDesktopComponent
  2275. // will fail to attempt to create a subscription if a NULL window handle is passed in.
  2276. if (!hwnd)
  2277. hwnd = GetLastActivePopup(GetActiveWindow());
  2278. compA.dwSize = sizeof(compA);
  2279. compA.dwCurItemState = (pcomp->dwSize != sizeof(IE4COMPONENT)) ? pcomp->dwCurItemState : IS_NORMAL;
  2280. SHUnicodeToTChar(pszSourceW, szSource, ARRAYSIZE(szSource));
  2281. pszExt = PathFindExtension(szSource);
  2282. fExtIsCdf = lstrcmpi(pszExt, TEXT(".CDF")) == 0;
  2283. fPathIsUrl = PathIsURL(szSource) && !UrlIsFileUrl(szSource);
  2284. if (FindComponent(szSource, (g_pActiveDesk ? g_pActiveDesk : this)))
  2285. {
  2286. if (dwFlags & ADDURL_SILENT)
  2287. {
  2288. if (FAILED(StringCchCopy(compA.szSource, ARRAYSIZE(compA.szSource), szSource)))
  2289. {
  2290. compA.szSource[0] = 0;
  2291. }
  2292. MultiCompToWideComp(&compA, pcomp);
  2293. RemoveDesktopItem(pcomp, 0);
  2294. }
  2295. else
  2296. {
  2297. // This is a long string. So,...
  2298. TCHAR szMsg[512];
  2299. TCHAR szMsg2[256];
  2300. TCHAR szTitle[128];
  2301. LoadString(HINST_THISDLL, IDS_COMP_EXISTS, szMsg, ARRAYSIZE(szMsg));
  2302. LoadString(HINST_THISDLL, IDS_COMP_EXISTS_2, szMsg2, ARRAYSIZE(szMsg2));
  2303. StringCchCat(szMsg, ARRAYSIZE(szMsg), szMsg2); // display, truncation fine
  2304. LoadString(HINST_THISDLL, IDS_COMP_TITLE, szTitle, ARRAYSIZE(szTitle));
  2305. MessageBox(hwnd, szMsg, szTitle, MB_OK);
  2306. fOkay = FALSE;
  2307. }
  2308. }
  2309. if (fOkay && CheckForExistingSubscription(szSource))
  2310. {
  2311. if ((dwFlags & ADDURL_SILENT) ||
  2312. (ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_COMP_SUBSCRIBED),
  2313. MAKEINTRESOURCE(IDS_COMP_TITLE), MB_YESNO) == IDYES))
  2314. {
  2315. DeleteFromSubscriptionList(szSource);
  2316. }
  2317. else
  2318. {
  2319. fOkay = FALSE;
  2320. }
  2321. }
  2322. if (fOkay)
  2323. {
  2324. if (fPathIsUrl || fExtIsCdf)
  2325. {
  2326. HRESULT hr;
  2327. IProgressDialog * pProgressDlg = NULL;
  2328. DECLAREWAITCURSOR;
  2329. // 98/12/16 vtan #250938: Cannot add new components that are not
  2330. // local with ICW run to completion. Tell the user and launch ICW.
  2331. if (!IsICWCompleted())
  2332. {
  2333. if ((dwFlags & ADDURL_SILENT) == 0)
  2334. {
  2335. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_COMP_ICW_ADD), MAKEINTRESOURCE(IDS_COMP_ICW_TITLE), MB_OK);
  2336. LaunchICW();
  2337. }
  2338. fOkay = FALSE;
  2339. }
  2340. else
  2341. {
  2342. SetWaitCursor();
  2343. // ParseDesktopComponent can hang for a long time, we need some sort of progress
  2344. // UI up before we call it.
  2345. if (!(dwFlags & ADDURL_SILENT) && !fExtIsCdf)
  2346. {
  2347. if (pProgressDlg = CProgressDialog_CreateInstance(IDS_COMP_TITLE, IDA_ISEARCH, g_hinst))
  2348. {
  2349. TCHAR szConnecting[80];
  2350. LoadString(HINST_THISDLL, IDS_CONNECTING, szConnecting, ARRAYSIZE(szConnecting));
  2351. pProgressDlg->SetLine(1, szConnecting, FALSE, NULL);
  2352. pProgressDlg->SetLine(2, szSource, TRUE, NULL);
  2353. pProgressDlg->StartProgressDialog(hwnd, NULL, PROGDLG_AUTOTIME | PROGDLG_NOPROGRESSBAR, NULL);
  2354. }
  2355. }
  2356. hr = ParseDesktopComponent(hwnd, szSource, pcomp);
  2357. if (pProgressDlg)
  2358. {
  2359. pProgressDlg->StopProgressDialog();
  2360. fOkay = !pProgressDlg->HasUserCancelled(); // User may have cancelled the progress dialog
  2361. pProgressDlg->Release();
  2362. }
  2363. ResetWaitCursor();
  2364. if (hr == S_FALSE) // User cancelled operation via subscription download dialog
  2365. fOkay = FALSE;
  2366. if (fOkay)
  2367. {
  2368. if (SUCCEEDED(hr))
  2369. {
  2370. //
  2371. // Convert ed's wide thinggy to multi.
  2372. //
  2373. WideCompToMultiComp(pcomp, &compA);
  2374. fSubscribed = TRUE;
  2375. }
  2376. else if (!fExtIsCdf)
  2377. {
  2378. //
  2379. // This is some non-CDF url.
  2380. //
  2381. CreateComponent(&compA, szSource);
  2382. }
  2383. else
  2384. {
  2385. //
  2386. // We barfed on a CDF, bring up an error message.
  2387. //
  2388. if (!(dwFlags & ADDURL_SILENT))
  2389. {
  2390. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_COMP_BADURL),
  2391. MAKEINTRESOURCE(IDS_COMP_TITLE), MB_OK);
  2392. }
  2393. fOkay = FALSE;
  2394. }
  2395. }
  2396. }
  2397. }
  2398. else
  2399. {
  2400. //
  2401. // This is just some local file.
  2402. //
  2403. CreateComponent(&compA, szSource);
  2404. }
  2405. }
  2406. if (fOkay && fPathIsUrl && !fSubscribed)
  2407. {
  2408. //
  2409. // Run subscription code on URLs if CDF code hasn't already.
  2410. //
  2411. if (dwFlags & ADDURL_SILENT)
  2412. {
  2413. ISubscriptionMgr *psm;
  2414. if (SUCCEEDED(CoCreateInstance(CLSID_SubscriptionMgr, NULL,
  2415. CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&psm)))
  2416. {
  2417. //We need to zero init this structure except the cbSize field.
  2418. SUBSCRIPTIONINFO siDefault = {sizeof(SUBSCRIPTIONINFO)};
  2419. //This field is already initialized above.
  2420. //siDefault.cbSize = sizeof(siDefault);
  2421. psm->CreateSubscription(hwnd, szSource, szSource, CREATESUBS_NOUI, SUBSTYPE_DESKTOPURL, &siDefault);
  2422. psm->UpdateSubscription(szSource);
  2423. psm->Release();
  2424. }
  2425. }
  2426. else
  2427. {
  2428. HRESULT hres = CreateSubscriptionsWizard(SUBSTYPE_DESKTOPURL, szSource, NULL, hwnd);
  2429. if (!SUCCEEDED(hres)) //Some error, or the user chose Cancel - we should fail.
  2430. {
  2431. ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_COMP_BADSUBSCRIBE),
  2432. MAKEINTRESOURCE(IDS_COMP_TITLE), MB_OK);
  2433. }
  2434. fOkay = (hres == S_OK); //could be S_FALSE, which means CreateSubscription was cancelled
  2435. //so we don't display the above error, but we don't create the DTI
  2436. }
  2437. }
  2438. MultiCompToWideComp(&compA, pcomp);
  2439. if (fOkay)
  2440. {
  2441. AddDesktopItem(pcomp, 0);
  2442. return S_OK;
  2443. }
  2444. else
  2445. {
  2446. return E_FAIL;
  2447. }
  2448. }
  2449. void CActiveDesktop::_SaveSettings(DWORD dwFlags)
  2450. {
  2451. ENTERPROC(2, "DS SaveSettings()");
  2452. if (dwFlags & AD_APPLY_SAVE)
  2453. {
  2454. // Don't ever modify the safemode settings
  2455. TCHAR szDeskcomp[MAX_PATH];
  2456. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, _pszScheme);
  2457. if (!StrStr(szDeskcomp, REG_DESKCOMP_SAFEMODE_SUFFIX))
  2458. {
  2459. //
  2460. // Write out registry settings.
  2461. //
  2462. _SaveWallpaper();
  2463. _SaveComponents();
  2464. _SavePattern(SAVE_PATTERN_NAME);
  2465. }
  2466. };
  2467. if (dwFlags & AD_APPLY_HTMLGEN)
  2468. {
  2469. //We need to generate the Patten.bmp file too!
  2470. _SavePattern(GENERATE_PATTERN_FILE);
  2471. //
  2472. // Write out HTML file.
  2473. //
  2474. _GenerateHtml();
  2475. }
  2476. // The 3rd largest hang found by WindowsUpdate crash uploader has been that the Desktop hwnd hangs
  2477. // and the display CPYU
  2478. #define SENDMESSAGE_TIMEOUT (10 * 1000)
  2479. if (dwFlags & AD_APPLY_REFRESH)
  2480. {
  2481. HWND hwndShell = GetShellWindow();
  2482. SHELLSTATE ss = {0};
  2483. DWORD_PTR pdwTemp = 0;
  2484. SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  2485. BOOL fWasActiveDesktop = BOOLIFY(ss.fDesktopHTML);
  2486. BOOL fIsActiveDesktop = BOOLIFY(_co.fActiveDesktop);
  2487. if (fIsActiveDesktop && !IsICWCompleted())
  2488. TBOOL(DisableUndisplayableComponents(this));
  2489. if (fIsActiveDesktop != fWasActiveDesktop)
  2490. {
  2491. if (hwndShell)
  2492. {
  2493. SendMessageTimeout(hwndShell, WM_WININICHANGE, SPI_SETDESKWALLPAPER, (LPARAM)TEXT("ToggleDesktop"), SMTO_NORMAL, SENDMESSAGE_TIMEOUT, &pdwTemp);
  2494. }
  2495. //Force a SHRefresh with this dummy call
  2496. SHGetSetSettings(NULL, 0, TRUE);
  2497. }
  2498. else if (fIsActiveDesktop && hwndShell)
  2499. {
  2500. //See if we can simply make the changes dynamically instead of refreshing the whole page
  2501. // 98/09/22 #182982 vtan: Use dynamic HTML to refresh only if specifically told by a flag.
  2502. if (_fUseDynamicHtml && (dwFlags & AD_APPLY_DYNAMICREFRESH))
  2503. {
  2504. SendMessageTimeout(hwndShell, DTM_MAKEHTMLCHANGES, (WPARAM)0, (LPARAM)0L, SMTO_NORMAL, SENDMESSAGE_TIMEOUT, &pdwTemp);
  2505. }
  2506. else
  2507. {
  2508. //Can't use dynamic html. We have to refresh the whole page.
  2509. SendMessageTimeout(hwndShell, WM_WININICHANGE, SPI_SETDESKWALLPAPER,
  2510. (LPARAM)((dwFlags & AD_APPLY_BUFFERED_REFRESH) ? c_szBufferedRefresh : c_szRefreshDesktop), SMTO_NORMAL, SENDMESSAGE_TIMEOUT, &pdwTemp);
  2511. }
  2512. }
  2513. _fUseDynamicHtml = TRUE;
  2514. }
  2515. //
  2516. // Data is no longer dirty.
  2517. //
  2518. _fDirty = FALSE;
  2519. _fWallpaperDirty = FALSE;
  2520. _fWallpaperChangedDuringInit = FALSE;
  2521. _fPatternDirty = FALSE;
  2522. EXITPROC(2, "DS SaveSettings!");
  2523. }
  2524. ULONG CActiveDesktop::AddRef(void)
  2525. {
  2526. ENTERPROC(1, "DS AddRef()");
  2527. _cRef++;
  2528. EXITPROC(1, "DS AddRef=%d", _cRef);
  2529. return _cRef;
  2530. }
  2531. // pwzPath: The path where the temp files go (%userprofile%/windows)
  2532. // pszFile: The original file name ("Joe's Vacation Picture.jpg")
  2533. // pszInUse: The wallpaper in use.
  2534. HRESULT _DeleteUnusedTempFiles(IN LPCWSTR pwzPath, IN LPCTSTR pszFile)
  2535. {
  2536. TCHAR szTemplate[MAX_PATH];
  2537. WIN32_FIND_DATA findFileData;
  2538. LPCTSTR pszFileName = PathFindFileName(pszFile);
  2539. HRESULT hr = StringCchPrintf(szTemplate, ARRAYSIZE(szTemplate), TEXT("%ls\\Wallpaper*.bmp"), pwzPath);
  2540. if (SUCCEEDED(hr))
  2541. {
  2542. HANDLE hFindFile = FindFirstFile(szTemplate, &findFileData);
  2543. if (INVALID_HANDLE_VALUE != hFindFile)
  2544. {
  2545. do
  2546. {
  2547. // Is this an old template? (Different name than we are currently using?
  2548. // Also, don't delete the wallpaper that is in use.
  2549. if (StrCmpI(findFileData.cFileName, pszFileName))
  2550. {
  2551. DeleteFile(szTemplate); // Yes so delete it.
  2552. }
  2553. }
  2554. while (FindNextFile(hFindFile, &findFileData));
  2555. FindClose(hFindFile);
  2556. }
  2557. }
  2558. return hr;
  2559. }
  2560. // nIndex: The file to try.
  2561. // pszInUse: This is the file we should skip because it's in use.
  2562. // pwzPath: On the way in, this is the selected wallpaper to convert.
  2563. // On the way out, this is is the converted file.
  2564. HRESULT _ConvertToTempFile(IN int nIndex, IN LPCWSTR pwzTempPath, IN LPTSTR pwzPath, IN int cchSize)
  2565. {
  2566. HRESULT hr = E_FAIL;
  2567. WCHAR wzNewFile[MAX_PATH];
  2568. LPCWSTR pszFileName = PathFindFileName(pwzPath);
  2569. if (pszFileName)
  2570. {
  2571. hr = StringCchPrintf(wzNewFile, ARRAYSIZE(wzNewFile), L"%s\\Wallpaper%d.bmp", pwzTempPath, nIndex);
  2572. if (SUCCEEDED(hr))
  2573. {
  2574. hr = SHConvertGraphicsFile(pwzPath, wzNewFile, SHCGF_REPLACEFILE);
  2575. // This may fail for one of many reasons, and we just fall back to the old behavior if it fails.
  2576. // This may fail if they don't have write permission of the disk, run out of disk space, or
  2577. // this is a file type that we don't support.
  2578. if (SUCCEEDED(hr))
  2579. {
  2580. hr = StringCchCopy(pwzPath, cchSize, wzNewFile);
  2581. }
  2582. }
  2583. }
  2584. return hr;
  2585. }
  2586. // pszFile: On the way in, this will contain the full path to the original file.
  2587. // On the way out, if we succeed, it will be modified to the temp file
  2588. // that is the converted equivalent of the file on the way in.
  2589. HRESULT CActiveDesktop::_ConvertFileToTempBitmap(IN LPWSTR pszFile, IN int cchSize)
  2590. {
  2591. HRESULT hr = E_FAIL;
  2592. WCHAR wzPath[MAX_PATH];
  2593. if (S_OK == SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wzPath) &&
  2594. PathAppend(wzPath, TEXT("Microsoft")))
  2595. {
  2596. CreateDirectoryW(wzPath, NULL);
  2597. // Let's try the modified names to come up with something we can use.
  2598. for (int nIndex = 1; FAILED(hr) && (nIndex < 100); nIndex++)
  2599. {
  2600. hr = _ConvertToTempFile(nIndex, wzPath, pszFile, cchSize);
  2601. }
  2602. if (SUCCEEDED(hr))
  2603. {
  2604. _DeleteUnusedTempFiles(wzPath, pszFile);
  2605. }
  2606. }
  2607. return hr;
  2608. }
  2609. #define SZ_REGKEY_CONTROLPANEL_DESKTOP TEXT("Control Panel\\Desktop")
  2610. #define SZ_REGVALUE_CONVERTED_WALLPAPER TEXT("ConvertedWallpaper")
  2611. #define SZ_REGVALUE_ORIGINAL_WALLPAPER TEXT("OriginalWallpaper") // We store this to find when someone changed the wallpaper around us
  2612. #define SZ_REGVALUE_WALLPAPER TEXT("Wallpaper")
  2613. #define SZ_REGVALUE_CONVERTED_WP_LASTWRITE TEXT("ConvertedWallpaper Last WriteTime")
  2614. HRESULT CActiveDesktop::_SaveTempWallpaperSettings(void)
  2615. {
  2616. HRESULT hr = E_FAIL;
  2617. // When we converted a non-.BMP wallpaper to a .bmp temp file,
  2618. // we keep the name of the original wallpaper path stored in _szSelectedWallpaper.
  2619. // We need to save that.
  2620. if (_szSelectedWallpaper)
  2621. {
  2622. hr = S_OK;
  2623. DWORD cbSize = sizeof(_szSelectedWallpaper[0]) * (lstrlen(_szSelectedWallpaper) + 1);
  2624. Str_SetPtr(&_pszOrigLastApplied, _szSelectedWallpaper);
  2625. // ISSUE: CONVERTED and ORIGINAL are backwards, but we shipped beta1 like this so we can't change it... blech
  2626. DWORD dwError = SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CONVERTED_WALLPAPER, REG_SZ, _szSelectedWallpaper, cbSize);
  2627. hr = HRESULT_FROM_WIN32(dwError);
  2628. if (SUCCEEDED(hr))
  2629. {
  2630. Str_SetPtrW(&_pszWallpaperInUse, _szSelectedWallpaper);
  2631. cbSize = sizeof(_szSelectedWallpaperConverted[0]) * (lstrlen(_szSelectedWallpaperConverted) + 1);
  2632. Str_SetPtr(&_pszOrigLastApplied, _szSelectedWallpaper);
  2633. dwError = SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_ORIGINAL_WALLPAPER, REG_SZ, (void *) _szSelectedWallpaperConverted, cbSize);
  2634. hr = HRESULT_FROM_WIN32(dwError);
  2635. if (SUCCEEDED(hr))
  2636. {
  2637. dwError = SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_WALLPAPER, REG_SZ, (void *) _szSelectedWallpaperConverted, cbSize);
  2638. hr = HRESULT_FROM_WIN32(dwError);
  2639. }
  2640. // Set date/time stamp of the original file (_szSelectedWallpaper) so we can later determine if the user changed the original.
  2641. if (_szSelectedWallpaper[0])
  2642. {
  2643. HANDLE hFile = CreateFile(_szSelectedWallpaper, GENERIC_READ, (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE),
  2644. NULL, OPEN_EXISTING, 0, NULL);
  2645. if (INVALID_HANDLE_VALUE != hFile)
  2646. {
  2647. if (GetFileTime(hFile, NULL, NULL, &_ftLastWrite))
  2648. {
  2649. dwError = SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CONVERTED_WP_LASTWRITE, REG_BINARY, &_ftLastWrite, sizeof(_ftLastWrite));
  2650. hr = HRESULT_FROM_WIN32(dwError);
  2651. }
  2652. CloseHandle(hFile);
  2653. }
  2654. }
  2655. else
  2656. {
  2657. ULARGE_INTEGER * puli = (ULARGE_INTEGER *) &_ftLastWrite;
  2658. puli->QuadPart = 0;
  2659. }
  2660. }
  2661. }
  2662. return hr;
  2663. }
  2664. HRESULT CActiveDesktop::ApplyChanges(DWORD dwFlags)
  2665. {
  2666. HRESULT hres = S_OK;
  2667. ENTERPROC(1, "DS Apply(dwFlags=%08X)", dwFlags);
  2668. BOOL fActiveDesktop = FALSE; // default to disable active desktop
  2669. // determine if we should enable active desktop
  2670. if (SHRestricted(REST_FORCEACTIVEDESKTOPON))
  2671. {
  2672. // if policy requires active desktop, then use that
  2673. fActiveDesktop = TRUE;
  2674. }
  2675. else
  2676. {
  2677. // if desktop components are locked -> active desktop is on
  2678. DWORD dwDesktopFlags = GetDesktopFlags();
  2679. if (dwDesktopFlags & COMPONENTS_LOCKED)
  2680. {
  2681. fActiveDesktop = TRUE;
  2682. }
  2683. else
  2684. {
  2685. // if desktop icons are hidden -> active desktop is on
  2686. SHELLSTATE ss;
  2687. SHGetSetSettings(&ss, SSF_HIDEICONS, FALSE);
  2688. if (ss.fHideIcons)
  2689. {
  2690. fActiveDesktop = TRUE;
  2691. }
  2692. }
  2693. }
  2694. // Convert the background if needed.
  2695. // if background is not a .bmp --> active desktop is on if we can't auto-convert
  2696. if (!IsNormalWallpaper(_szSelectedWallpaper))
  2697. {
  2698. BOOL fBitmapWallpaper = FALSE;
  2699. // create the factory
  2700. IShellImageDataFactory* pImgFact;
  2701. hres = CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC_SERVER,
  2702. IID_PPV_ARG(IShellImageDataFactory, &pImgFact));
  2703. if (SUCCEEDED(hres))
  2704. {
  2705. IShellImageData * pImage;
  2706. hres = pImgFact->CreateImageFromFile(_szSelectedWallpaper, &pImage);
  2707. if (SUCCEEDED(hres))
  2708. {
  2709. // PERF: cache decoded data
  2710. hres = pImage->Decode(SHIMGDEC_DEFAULT, 0, 0);
  2711. if (SUCCEEDED(hres))
  2712. {
  2713. if (S_FALSE == pImage->IsTransparent() &&
  2714. S_FALSE == pImage->IsAnimated())
  2715. {
  2716. hres = StringCchCopy(_szSelectedWallpaperConverted, ARRAYSIZE(_szSelectedWallpaperConverted), _szSelectedWallpaper);
  2717. if (SUCCEEDED(hres))
  2718. {
  2719. HRESULT hrConvert = _ConvertFileToTempBitmap(_szSelectedWallpaperConverted, ARRAYSIZE(_szSelectedWallpaperConverted));
  2720. if (SUCCEEDED(hrConvert))
  2721. {
  2722. if (S_OK == hrConvert) // if we actually had to convert (we may have already done the conversion)
  2723. {
  2724. _fDirty = TRUE; // if we converted, then we have changed the background and must persist it
  2725. _SaveTempWallpaperSettings();
  2726. hres = StringCchCopy(_szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper), _szSelectedWallpaperConverted);
  2727. }
  2728. fBitmapWallpaper = TRUE;
  2729. }
  2730. }
  2731. }
  2732. }
  2733. pImage->Release();
  2734. }
  2735. pImgFact->Release();
  2736. }
  2737. if (!fBitmapWallpaper)
  2738. {
  2739. fActiveDesktop = TRUE;
  2740. }
  2741. }
  2742. if (!fActiveDesktop)
  2743. {
  2744. // if any elements are checked --> active desktop is on
  2745. if (_hdsaComponent)
  2746. {
  2747. INT cComponents = DSA_GetItemCount(_hdsaComponent);
  2748. for (INT i = 0; i < cComponents; i++)
  2749. {
  2750. COMPONENTA* pComponent = (COMPONENTA*)DSA_GetItemPtr(_hdsaComponent, i);
  2751. if (pComponent && pComponent->fChecked)
  2752. {
  2753. fActiveDesktop = TRUE;
  2754. break;
  2755. }
  2756. }
  2757. }
  2758. }
  2759. if (_co.fActiveDesktop != fActiveDesktop)
  2760. {
  2761. _co.fActiveDesktop = fActiveDesktop;
  2762. _fDirty = TRUE;
  2763. }
  2764. if (dwFlags & AD_APPLY_FORCE)
  2765. {
  2766. _fDirty = TRUE;
  2767. _fWallpaperDirty = TRUE;
  2768. _fPatternDirty = TRUE;
  2769. }
  2770. if (_fDirty || _fWallpaperChangedDuringInit)
  2771. {
  2772. _SaveSettings(dwFlags);
  2773. }
  2774. EXITPROC(1, "DS ApplyChanges=%d", hres);
  2775. return S_OK;
  2776. }
  2777. ULONG CActiveDesktop::Release(void)
  2778. {
  2779. UINT nRet = --_cRef;
  2780. ENTERPROC(1, "DS Release()");
  2781. if (_cRef == 0)
  2782. {
  2783. delete this;
  2784. }
  2785. EXITPROC(1, "DS Release=%d", nRet);
  2786. return nRet;
  2787. }
  2788. CActiveDesktop::CActiveDesktop()
  2789. {
  2790. _cRef = 1;
  2791. _fNoDeskMovr = FALSE;
  2792. _fBackgroundHtml = FALSE;
  2793. _fUseDynamicHtml = TRUE;
  2794. _hdsaComponent = NULL;
  2795. _pszScheme = NULL;
  2796. DllAddRef();
  2797. }
  2798. CActiveDesktop::~CActiveDesktop()
  2799. {
  2800. if (_hdsaComponent)
  2801. {
  2802. DSA_Destroy(_hdsaComponent);
  2803. }
  2804. if (_pszScheme)
  2805. {
  2806. LocalFree((HANDLE)_pszScheme);
  2807. }
  2808. DllRelease();
  2809. }
  2810. HRESULT CActiveDesktop::GetWallpaper(LPWSTR pwszWallpaper, UINT cchWallpaper, DWORD dwReserved)
  2811. {
  2812. HRESULT hres = E_INVALIDARG;
  2813. ENTERPROC(1, "DS GetWallpaper(pszWallpaper=%08X,cchWallpaper=%d)", pwszWallpaper, cchWallpaper);
  2814. ASSERT(!dwReserved); // These should be 0
  2815. if (pwszWallpaper && cchWallpaper)
  2816. {
  2817. hres = StringCchCopy(pwszWallpaper, cchWallpaper, _szSelectedWallpaper);
  2818. if (SUCCEEDED(hres))
  2819. {
  2820. if ( cchWallpaper < wcslen(_szSelectedWallpaper) )
  2821. {
  2822. hres = MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_MORE_DATA );
  2823. }
  2824. else
  2825. {
  2826. hres = S_OK;
  2827. }
  2828. }
  2829. }
  2830. if (FAILED(hres))
  2831. {
  2832. TraceMsg(TF_WARNING, "DS GetWallpaper unable to return wallpaper");
  2833. }
  2834. EXITPROC(1, "DS GetWallpaper=%d", hres);
  2835. return hres;
  2836. }
  2837. HRESULT CActiveDesktop::SetWallpaper(LPCWSTR pwszWallpaper, DWORD dwReserved)
  2838. {
  2839. HRESULT hres = E_INVALIDARG;
  2840. WCHAR szTemp[MAX_PATH];
  2841. ASSERT(!dwReserved); // These should be 0
  2842. if (_fPolicyForWPName) // If a policy exists, the caller can not change the wallpaper.
  2843. return S_FALSE;
  2844. if (pwszWallpaper)
  2845. {
  2846. hres = StringCchCopy(szTemp, ARRAYSIZE(szTemp), pwszWallpaper);
  2847. if (SUCCEEDED(hres))
  2848. {
  2849. hres = PathExpandEnvStringsWrap(szTemp, ARRAYSIZE(szTemp)); // We unexpand only when we persist.
  2850. if (SUCCEEDED(hres))
  2851. {
  2852. if (lstrcmp(_szSelectedWallpaper, szTemp) != 0)
  2853. {
  2854. hres = StringCchCopy(_szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper), szTemp);
  2855. if (SUCCEEDED(hres))
  2856. {
  2857. _fWallpaperDirty = TRUE;
  2858. _fDirty = TRUE;
  2859. _fUseDynamicHtml = FALSE; //Setting wallpaper causes a lot of change; So, can't use dynamic html
  2860. }
  2861. }
  2862. }
  2863. }
  2864. }
  2865. ENTERPROC(1, "DS SetWallpaper(pszWallpaper=>%s<)", pwszWallpaper ? szTemp : TEXT("(NULL)"));
  2866. EXITPROC(1, "DS SetWallpaper=%d", hres);
  2867. return hres;
  2868. }
  2869. HRESULT CActiveDesktop::GetWallpaperOptions(WALLPAPEROPT *pwpo, DWORD dwReserved)
  2870. {
  2871. HRESULT hres = E_INVALIDARG;
  2872. ENTERPROC(1, "DS GetWallpaperOptions(pwpo=%08X)");
  2873. ASSERT(!dwReserved); // These should be 0
  2874. if ((pwpo) && (pwpo->dwSize == sizeof(*pwpo)))
  2875. {
  2876. *pwpo = _wpo;
  2877. hres = S_OK;
  2878. }
  2879. else
  2880. {
  2881. TraceMsg(TF_WARNING, "DS GetWallpaperOptions could not return options");
  2882. }
  2883. EXITPROC(1, "DS GetWallpaperOptions=%d", hres);
  2884. return hres;
  2885. }
  2886. HRESULT CActiveDesktop::SetWallpaperOptions(LPCWALLPAPEROPT pwpo, DWORD dwReserved)
  2887. {
  2888. HRESULT hres = E_INVALIDARG;
  2889. ENTERPROC(1, "DS SetWallpaperOptions(pwpo=%08X)", pwpo);
  2890. ASSERT(!dwReserved); // These should be 0
  2891. if (_fPolicyForWPStyle) //If a policy exists for wallpaper style, the caller can not change it.
  2892. return S_FALSE;
  2893. if ((pwpo) && (pwpo->dwSize == sizeof(*pwpo)))
  2894. {
  2895. _wpo = *pwpo;
  2896. _fWallpaperDirty = TRUE;
  2897. _fDirty = TRUE;
  2898. _fUseDynamicHtml = FALSE; //Changing wallpaper options causes us to regenerate the whole thing.
  2899. hres = S_OK;
  2900. }
  2901. else
  2902. {
  2903. TraceMsg(TF_WARNING, "DS SetWallpaperOptions could not set options");
  2904. }
  2905. EXITPROC(1, "DS SetWallpaperOptions=%d", hres);
  2906. return hres;
  2907. }
  2908. HRESULT CActiveDesktop::GetPattern(LPWSTR pwszPattern, UINT cchPattern, DWORD dwReserved)
  2909. {
  2910. HRESULT hres;
  2911. ENTERPROC(1, "DS GetPattern(psz=%08X,cch=%d)", pwszPattern, cchPattern);
  2912. ASSERT(!dwReserved); // These should be 0
  2913. if (!pwszPattern || (cchPattern == 0))
  2914. {
  2915. hres = E_INVALIDARG;
  2916. }
  2917. else
  2918. {
  2919. hres = StringCchCopy(pwszPattern, cchPattern, _szSelectedPattern);
  2920. }
  2921. EXITPROC(1, "DS GetPattern=%d", hres);
  2922. return hres;
  2923. }
  2924. HRESULT CActiveDesktop::SetPattern(LPCWSTR pwszPattern, DWORD dwReserved)
  2925. {
  2926. ENTERPROC(1, "DS SetPattern(psz=>%s<)", pwszPattern ? pwszPattern : TEXT("(NULL)"));
  2927. HRESULT hres = E_INVALIDARG;
  2928. ASSERT(!dwReserved); // These should be 0
  2929. if (pwszPattern)
  2930. {
  2931. if (lstrcmp(_szSelectedPattern, pwszPattern) != 0)
  2932. {
  2933. hres = StringCchCopy(_szSelectedPattern, ARRAYSIZE(_szSelectedPattern), pwszPattern);
  2934. if (SUCCEEDED(hres))
  2935. {
  2936. _fPatternDirty = TRUE;
  2937. _fDirty = TRUE;
  2938. _fUseDynamicHtml = FALSE; //Setting pattern causes us to regenerate the whole thing.
  2939. }
  2940. }
  2941. else
  2942. {
  2943. hres = E_FAIL;
  2944. }
  2945. }
  2946. EXITPROC(1, "DS SetPattern=%d", hres);
  2947. return hres;
  2948. }
  2949. HRESULT CActiveDesktop::GetDesktopItemOptions(COMPONENTSOPT *pco, DWORD dwReserved)
  2950. {
  2951. HRESULT hres = E_INVALIDARG;
  2952. ENTERPROC(1, "DS GetComponentsOptions(pco=%08X)", pco);
  2953. ASSERT(!dwReserved); // These should be 0
  2954. if (pco && (pco->dwSize == sizeof(*pco)))
  2955. {
  2956. *pco = _co;
  2957. hres = S_OK;
  2958. }
  2959. else
  2960. {
  2961. TraceMsg(TF_WARNING, "DS GetComponentsOptions unable to return options");
  2962. }
  2963. EXITPROC(1, "DS GetComponentsOptions=%d", hres);
  2964. return hres;
  2965. }
  2966. HRESULT CActiveDesktop::SetDesktopItemOptions(LPCCOMPONENTSOPT pco, DWORD dwReserved)
  2967. {
  2968. HRESULT hres = E_INVALIDARG;
  2969. ENTERPROC(1, "DS SetComponentsOptions(pco=%08X)", pco);
  2970. ASSERT(!dwReserved); // These should be 0
  2971. if (pco && (pco->dwSize == sizeof(*pco)))
  2972. {
  2973. _co = *pco;
  2974. _fDirty = TRUE;
  2975. hres = S_OK;
  2976. }
  2977. else
  2978. {
  2979. TraceMsg(TF_WARNING, "DS SetComponentsOptions unable to set options");
  2980. }
  2981. EXITPROC(1, "DS SetComponentsOptions=%d", hres);
  2982. return hres;
  2983. }
  2984. //
  2985. // SetStateInfo()
  2986. // This function simply sets up the COMPSTATEINFO structure passed using the current
  2987. // position and size from the COMPPOS structure and the itemState passed.
  2988. //
  2989. void SetStateInfo(COMPSTATEINFO *pCompStateInfo, COMPPOS *pCompPos, DWORD dwItemState)
  2990. {
  2991. pCompStateInfo->dwSize = sizeof(*pCompStateInfo);
  2992. pCompStateInfo->iLeft = pCompPos->iLeft;
  2993. pCompStateInfo->iTop = pCompPos->iTop;
  2994. pCompStateInfo->dwWidth = pCompPos->dwWidth;
  2995. pCompStateInfo->dwHeight = pCompPos->dwHeight;
  2996. pCompStateInfo->dwItemState = dwItemState;
  2997. }
  2998. void ConvertCompStruct(COMPONENTA *pCompDest, COMPONENTA *pCompSrc, BOOL fPubToPriv)
  2999. {
  3000. pCompDest -> dwID = pCompSrc -> dwID;
  3001. pCompDest -> iComponentType = pCompSrc -> iComponentType;
  3002. pCompDest -> fChecked = pCompSrc -> fChecked;
  3003. pCompDest -> fDirty = pCompSrc -> fDirty;
  3004. pCompDest -> fNoScroll = pCompSrc -> fNoScroll;
  3005. pCompDest -> cpPos = pCompSrc -> cpPos;
  3006. if (fPubToPriv)
  3007. {
  3008. COMPONENT *pComp = (COMPONENT *)pCompSrc;
  3009. pCompDest->dwSize = sizeof(COMPONENTA);
  3010. SHUnicodeToTChar(pComp->wszSource, pCompDest->szSource, ARRAYSIZE(pCompDest->szSource));
  3011. SHUnicodeToTChar(pComp->wszFriendlyName, pCompDest->szFriendlyName, ARRAYSIZE(pCompDest->szFriendlyName));
  3012. SHUnicodeToTChar(pComp->wszSubscribedURL, pCompDest->szSubscribedURL, ARRAYSIZE(pCompDest->szSubscribedURL));
  3013. //Check to see if the public component is from IE4 app (old size)
  3014. if (pCompSrc->dwSize == sizeof(COMPONENT))
  3015. {
  3016. // Since the dest component is the same size as the most current structure, all fields
  3017. // are valid.
  3018. // CAUTION: The following fields are at a different offset in public and private
  3019. // structures. So, you need to use pcomp instead of pCompSrc for example.
  3020. pCompDest->dwCurItemState = pComp->dwCurItemState;
  3021. pCompDest->csiOriginal = pComp->csiOriginal;
  3022. pCompDest->csiRestored = pComp->csiRestored;
  3023. }
  3024. else
  3025. {
  3026. // Since the size did not match, we assume that this is an older structure.
  3027. // Since the older struct does not have any Original and Restored sizes, let's copy
  3028. // the default values.
  3029. IE4COMPONENT *pIE4Comp = (IE4COMPONENT *)pCompSrc;
  3030. pCompDest->dwCurItemState = IS_NORMAL;
  3031. SetStateInfo(&pCompDest->csiOriginal, &pIE4Comp->cpPos, IS_NORMAL);
  3032. SetStateInfo(&pCompDest->csiRestored, &pIE4Comp->cpPos, IS_NORMAL);
  3033. }
  3034. }
  3035. else
  3036. {
  3037. COMPONENT *pComp = (COMPONENT *)pCompDest;
  3038. if (pCompDest->dwSize != sizeof(COMPONENT))
  3039. pCompDest->dwSize = sizeof(IE4COMPONENT);
  3040. SHTCharToUnicode(pCompSrc->szSource, pComp->wszSource, ARRAYSIZE(pComp->wszSource));
  3041. SHTCharToUnicode(pCompSrc->szFriendlyName, pComp->wszFriendlyName, ARRAYSIZE(pComp->wszFriendlyName));
  3042. SHTCharToUnicode(pCompSrc->szSubscribedURL, pComp->wszSubscribedURL, ARRAYSIZE(pComp->wszSubscribedURL));
  3043. //Check to see if the public component is from IE4 app (old size)
  3044. if (pComp->dwSize == sizeof(COMPONENT))
  3045. {
  3046. // Since the dest component is the same size as the most current structure, all fields
  3047. // are valid.
  3048. // CAUTION: The following fields are at a different offset in public and private
  3049. // structures. So, you need to use pcomp instead of pCompDest for example.
  3050. pComp->dwCurItemState = pCompSrc->dwCurItemState;
  3051. pComp->csiOriginal = pCompSrc->csiOriginal;
  3052. pComp->csiRestored = pCompSrc->csiRestored;
  3053. }
  3054. // else, the dest component is IE4COMPONENT and the additional fields are not there.
  3055. }
  3056. }
  3057. HRESULT CActiveDesktop::_AddDTIWithUIPrivateA(HWND hwnd, LPCCOMPONENT pComp, DWORD dwFlags)
  3058. {
  3059. HRESULT hres = E_FAIL;
  3060. PCWSTR pszUrl = pComp->wszSource;
  3061. int nScheme = GetUrlScheme(pszUrl);
  3062. DWORD dwCurItemState;
  3063. if ((URL_SCHEME_INVALID == nScheme) || (URL_SCHEME_UNKNOWN == nScheme))
  3064. {
  3065. TCHAR szFullyQualified[INTERNET_MAX_URL_LENGTH];
  3066. DWORD cchSize = ARRAYSIZE(szFullyQualified);
  3067. if (SUCCEEDED(ParseURLFromOutsideSource(pszUrl, szFullyQualified, &cchSize, NULL)))
  3068. nScheme = GetUrlScheme(szFullyQualified);
  3069. }
  3070. // Is this URL valid to subscribe to? Did the caller specify they want use
  3071. // to try to subscribe to it?
  3072. if ((URL_SCHEME_FILE != nScheme) && (URL_SCHEME_ABOUT != nScheme) &&
  3073. IsFlagSet(dwFlags, DTI_ADDUI_DISPSUBWIZARD) && hwnd)
  3074. {
  3075. //Create a subscription.
  3076. hres = CreateSubscriptionsWizard(SUBSTYPE_DESKTOPURL, pszUrl, NULL, hwnd);
  3077. if (hres != S_OK)
  3078. {
  3079. return hres;
  3080. }
  3081. }
  3082. //
  3083. // Add the component to the registry.
  3084. //
  3085. // PERF: This function creates a second COM objects.
  3086. // We need to Inline the functionality.
  3087. if (pComp->dwSize == sizeof(IE4COMPONENT))
  3088. dwCurItemState = IS_NORMAL;
  3089. else
  3090. dwCurItemState = pComp->dwCurItemState;
  3091. hres = AddRemoveDesktopComponentNoUI(TRUE, AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH, pszUrl, NULL, pComp->iComponentType,
  3092. pComp->cpPos.iLeft, pComp->cpPos.iTop, pComp->cpPos.dwWidth, pComp->cpPos.dwHeight, TRUE, dwCurItemState) ? S_OK : E_FAIL;
  3093. return hres;
  3094. }
  3095. #define STC_DESKTOPCOMPONENT 0x00000002
  3096. STDAPI SubscribeToCDF(HWND hwndParent, LPCWSTR pwzUrl, DWORD dwCDFTypes);
  3097. HRESULT CActiveDesktop::AddDesktopItemWithUI(HWND hwnd, LPCOMPONENT pComp, DWORD dwFlags)
  3098. {
  3099. HRESULT hres = E_FAIL;
  3100. // We need to support IE4 apps calling with the old component structure too!
  3101. // We use the size field to detect IE4 v/s newer apps!
  3102. if (!pComp ||
  3103. ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT))) ||
  3104. ((pComp->dwSize == sizeof(*pComp)) && !VALIDATESTATE(pComp->dwCurItemState)) ||
  3105. ((pComp->iComponentType < 0) || (pComp->iComponentType > COMP_TYPE_MAX))) //Validate the component type
  3106. return E_INVALIDARG;
  3107. // Catch folks that call our API's to add components and prevent them from doing
  3108. // so if the restriction is in place.
  3109. if (SHIsRestricted(NULL, REST_NOADDDESKCOMP))
  3110. return E_ACCESSDENIED;
  3111. // Check if the component already exists.
  3112. BOOL fCompExists = FALSE;
  3113. int cComp;
  3114. GetDesktopItemCount(&cComp, 0);
  3115. int i;
  3116. COMPONENT comp;
  3117. comp.dwSize = sizeof(COMPONENT); //This needs to be initialized for ConvertCompStruc to work!
  3118. COMPONENTA compA;
  3119. TCHAR szSource[INTERNET_MAX_URL_LENGTH];
  3120. SHUnicodeToTChar(pComp->wszSource, szSource, ARRAYSIZE(szSource));
  3121. for (i=0; i<cComp && !fCompExists; i++)
  3122. {
  3123. compA.dwSize = sizeof(compA);
  3124. if (GetComponentPrivate(i, &compA)
  3125. && lstrcmpi(szSource, compA.szSource) == 0)
  3126. {
  3127. fCompExists = TRUE;
  3128. ConvertCompStruct((COMPONENTA *)&comp, &compA, FALSE);
  3129. break;
  3130. }
  3131. }
  3132. BOOL fAskToInstall;
  3133. if (ZoneCheckUrlW(pComp->wszSource, URLACTION_SHELL_INSTALL_DTITEMS, (PUAF_NOUI), NULL) == S_OK)
  3134. {
  3135. fAskToInstall = TRUE;
  3136. }
  3137. else
  3138. {
  3139. fAskToInstall = FALSE;
  3140. }
  3141. if (S_OK != ZoneCheckUrlW(pComp->wszSource, URLACTION_SHELL_INSTALL_DTITEMS, (hwnd ? (PUAF_FORCEUI_FOREGROUND | PUAF_WARN_IF_DENIED) : PUAF_NOUI), NULL))
  3142. return E_ACCESSDENIED;
  3143. BOOL fCompSubDeleted = FALSE;
  3144. SUBSCRIPTIONINFO si = {sizeof(SUBSCRIPTIONINFO)};
  3145. // si.bstrUserName = NULL;
  3146. // si.bstrPassword = NULL;
  3147. // si.bstrFriendlyName = NULL;
  3148. //
  3149. // Confirmation dialog.
  3150. //
  3151. if (hwnd)
  3152. {
  3153. if (fCompExists)
  3154. {
  3155. //Prompt the user to delete the existing ADI.
  3156. // This is a long string. So,...
  3157. TCHAR szMsg[512];
  3158. TCHAR szMsg2[256];
  3159. TCHAR szTitle[128];
  3160. LoadString(HINST_THISDLL, IDS_COMP_EXISTS, szMsg, ARRAYSIZE(szMsg));
  3161. LoadString(HINST_THISDLL, IDS_COMP_EXISTS_2, szMsg2, ARRAYSIZE(szMsg2));
  3162. StringCchCat(szMsg, ARRAYSIZE(szMsg), szMsg2); // truncation is fine, this is display text
  3163. LoadString(HINST_THISDLL, IDS_COMP_TITLE, szTitle, ARRAYSIZE(szTitle));
  3164. MessageBox(hwnd, szMsg, szTitle, MB_OK);
  3165. return E_FAIL;
  3166. }
  3167. else if (fAskToInstall)
  3168. {
  3169. if (ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_CONFIRM_ADD),
  3170. MAKEINTRESOURCE(IDS_INTERNET_EXPLORER), MB_YESNO) != IDYES)
  3171. {
  3172. return E_FAIL; //User choses not to install this desktop component!
  3173. }
  3174. }
  3175. }
  3176. hres = SubscribeToCDF(hwnd, pComp->wszSubscribedURL, STC_DESKTOPCOMPONENT);
  3177. switch(hres)
  3178. {
  3179. case E_INVALIDARG:
  3180. {
  3181. // E_UNEXPECTED is returned from SubscribeToCDFUrlA() when the URL doesn't point to
  3182. // a CDF file, so we assume it's a web page.
  3183. hres = _AddDTIWithUIPrivateA(hwnd, pComp, dwFlags);
  3184. if (hres != S_OK && fCompSubDeleted) // Restore the old component
  3185. {
  3186. hres = AddDesktopItem(&comp, 0);
  3187. if (SUCCEEDED(hres))
  3188. {
  3189. ISubscriptionMgr *psm;
  3190. if (SUCCEEDED(CoCreateInstance(CLSID_SubscriptionMgr, NULL,
  3191. CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&psm)))
  3192. {
  3193. si.cbSize = sizeof(si);
  3194. psm->CreateSubscription(hwnd, comp.wszSubscribedURL, si.bstrFriendlyName, CREATESUBS_NOUI, SUBSTYPE_DESKTOPURL, &si);
  3195. psm->Release();
  3196. }
  3197. else
  3198. {
  3199. TraceMsg(TF_WARNING, "CActiveDesktop::AddDesktopItemWithUI : CoCreateInstance for CLSID_SubscriptionMgr failed.");
  3200. }
  3201. }
  3202. }
  3203. ApplyChanges(AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH);
  3204. }
  3205. break;
  3206. case E_ACCESSDENIED:
  3207. // The file was a CDF but didn't contain Desktop Component Information
  3208. if (hwnd)
  3209. {
  3210. TCHAR szMsg[MAX_PATH];
  3211. TCHAR szTitle[MAX_PATH];
  3212. LoadString(HINST_THISDLL, IDS_ADDCOMP_ERROR_CDFNODTI, szMsg, ARRAYSIZE(szMsg));
  3213. LoadString(HINST_THISDLL, IDS_INTERNET_EXPLORER, szTitle, ARRAYSIZE(szTitle));
  3214. MessageBox(hwnd, szMsg, szTitle, MB_OK);
  3215. }
  3216. break;
  3217. case E_UNEXPECTED:
  3218. // This was a CDF but it was misauthored.
  3219. if (hwnd)
  3220. {
  3221. TCHAR szMsg[MAX_PATH];
  3222. TCHAR szTitle[MAX_PATH];
  3223. LoadString(HINST_THISDLL, IDS_ADDCOMP_ERROR_CDFINALID, szMsg, ARRAYSIZE(szMsg));
  3224. LoadString(HINST_THISDLL, IDS_INTERNET_EXPLORER, szTitle, ARRAYSIZE(szTitle));
  3225. MessageBox(hwnd, szMsg, szTitle, MB_OK);
  3226. }
  3227. break;
  3228. default:
  3229. break;
  3230. }
  3231. if (hwnd && SUCCEEDED(hres))
  3232. {
  3233. // If the active desktop is currently OFF, we need to turn it ON
  3234. SHELLSTATE ss = {0};
  3235. SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  3236. if (!ss.fDesktopHTML)
  3237. {
  3238. COMPONENTSOPT co;
  3239. co.dwSize = sizeof(COMPONENTSOPT);
  3240. GetDesktopItemOptions(&co, 0);
  3241. co.fActiveDesktop = TRUE;
  3242. SetDesktopItemOptions(&co, 0);
  3243. ApplyChanges(AD_APPLY_REFRESH | AD_APPLY_DYNAMICREFRESH);
  3244. }
  3245. }
  3246. if (fCompSubDeleted)
  3247. {
  3248. if (si.bstrUserName)
  3249. {
  3250. SysFreeString(si.bstrUserName);
  3251. }
  3252. if (si.bstrPassword)
  3253. {
  3254. SysFreeString(si.bstrPassword);
  3255. }
  3256. if (si.bstrFriendlyName)
  3257. {
  3258. SysFreeString(si.bstrFriendlyName);
  3259. }
  3260. }
  3261. return hres;
  3262. }
  3263. void RestoreComponent(HDSA hdsaComponents, COMPONENTA * pcomp)
  3264. {
  3265. int i;
  3266. // If we are split then set the bit saying that the listview needs to be adjusted. This is done
  3267. // when we check the state of desktop.htm in EnsureUpdateHtml.
  3268. // Note: Do this only if this component is enabled.
  3269. if ((pcomp->dwCurItemState & IS_SPLIT) && (pcomp->fChecked))
  3270. {
  3271. pcomp->dwCurItemState |= IS_ADJUSTLISTVIEW;
  3272. SetDesktopFlags(COMPONENTS_ZOOMDIRTY, COMPONENTS_ZOOMDIRTY);
  3273. }
  3274. for (i = 0; i < DSA_GetItemCount(hdsaComponents); i++)
  3275. {
  3276. COMPONENTA * pcompT;
  3277. if (pcompT = (COMPONENTA *)DSA_GetItemPtr(hdsaComponents, i))
  3278. {
  3279. // If this component is split/fullscreen and is different from the source component
  3280. // but it is at the same location then it must be on this monitor (work area) so restore it.
  3281. if (ISZOOMED(pcompT) &&
  3282. lstrcmpi(pcomp->szSource, pcompT->szSource) &&
  3283. (pcomp->cpPos.iTop == pcompT->cpPos.iTop) &&
  3284. ((pcomp->cpPos.iLeft + pcomp->cpPos.dwWidth) == (pcompT->cpPos.iLeft + pcompT->cpPos.dwWidth)))
  3285. {
  3286. pcompT->dwCurItemState = pcompT->csiRestored.dwItemState;
  3287. pcompT->cpPos.iLeft = pcompT->csiRestored.iLeft;
  3288. pcompT->cpPos.iTop = pcompT->csiRestored.iTop;
  3289. pcompT->cpPos.dwWidth = pcompT->csiRestored.dwWidth;
  3290. pcompT->cpPos.dwHeight = pcompT->csiRestored.dwHeight;
  3291. pcompT->cpPos.izIndex = COMPONENT_TOP;
  3292. pcompT->fDirty = TRUE;
  3293. break;
  3294. }
  3295. }
  3296. }
  3297. }
  3298. HRESULT CActiveDesktop::AddDesktopItem(LPCCOMPONENT pComp, DWORD dwReserved)
  3299. {
  3300. HRESULT hres = E_FAIL;
  3301. COMPONENTA CompA;
  3302. CompA.dwSize = sizeof(CompA);
  3303. ASSERT(!dwReserved); // These should be 0
  3304. // We need to support IE4 apps calling with the old component structure too!
  3305. // We use the size field to detect IE4 v/s newer apps!
  3306. if (!pComp ||
  3307. ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT))) ||
  3308. ((pComp->dwSize == sizeof(*pComp)) && !VALIDATESTATE(pComp->dwCurItemState)))
  3309. return E_INVALIDARG;
  3310. // Catch folks that call our API's to add components and prevent them from doing
  3311. // so if the restriction is in place.
  3312. if ((!_fIgnoreAddRemovePolicies) && (SHIsRestricted(NULL, REST_NOADDDESKCOMP)))
  3313. return E_ACCESSDENIED;
  3314. // Convert the external structure to the internal format
  3315. ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE);
  3316. // If the component is already present, then fail the call!
  3317. if (_FindComponentBySource(CompA.szSource, &CompA) > -1)
  3318. return hres;
  3319. //Make sure that the COMPPOS size field is set before we add it!
  3320. CompA.cpPos.dwSize = sizeof(COMPPOS);
  3321. PositionComponent(&CompA, &CompA.cpPos, CompA.iComponentType, TRUE);
  3322. if (_hdsaComponent && ISZOOMED(&CompA))
  3323. RestoreComponent(_hdsaComponent, &CompA);
  3324. //Make sure the this component's fDirty flag is off.
  3325. CompA.fDirty = FALSE;
  3326. // Set the dummy bit here - this forces folks to do bitwise testing on the dwCurItemState field
  3327. // instead of testing for equality. This will allow us to expand use of the field down the
  3328. // road without compatibility problems.
  3329. CompA.dwCurItemState |= IS_INTERNALDUMMYBIT;
  3330. if (AddComponentPrivate(&CompA, _dwNextID++))
  3331. {
  3332. // It might be cheaper to attempt to insert the component in the
  3333. // correct z-order but it's less code to just call _SortAndRationalize
  3334. // after the insertion is done.
  3335. _SortAndRationalize();
  3336. hres = S_OK;
  3337. }
  3338. return(hres);
  3339. }
  3340. BOOL CActiveDesktop::AddComponentPrivate(COMPONENTA *pcomp, DWORD dwID)
  3341. {
  3342. BOOL fRet = FALSE;
  3343. ENTERPROC(1, "DS AddComponent(pcomp=%08X)", pcomp);
  3344. if (pcomp)
  3345. {
  3346. if (_hdsaComponent == NULL)
  3347. {
  3348. _hdsaComponent = DSA_Create(sizeof(COMPONENTA), DXA_GROWTH_CONST);
  3349. }
  3350. if (_hdsaComponent)
  3351. {
  3352. pcomp->dwID = dwID;
  3353. if (DSA_AppendItem(_hdsaComponent, pcomp) != -1)
  3354. {
  3355. _fDirty = TRUE;
  3356. fRet = TRUE;
  3357. }
  3358. else
  3359. {
  3360. TraceMsg(TF_WARNING, "DS AddComponent unable to append DSA");
  3361. }
  3362. }
  3363. else
  3364. {
  3365. TraceMsg(TF_WARNING, "DS AddComponent unable to create DSA");
  3366. }
  3367. }
  3368. else
  3369. {
  3370. TraceMsg(TF_WARNING, "DS AddComponent unable to add a component");
  3371. }
  3372. EXITPROC(1, "DS AddComponent=%d", fRet);
  3373. return fRet;
  3374. }
  3375. //
  3376. // This finds out if a given component already exists by comparing the szSource
  3377. // If so, it fills out the correct dwID and returns the index.
  3378. //
  3379. int CActiveDesktop::_FindComponentBySource(LPTSTR lpszSource, COMPONENTA *pComp)
  3380. {
  3381. int iRet = -1;
  3382. ENTERPROC(2, "DS FindComponentIdBySource(pComp=%8X)", pComp);
  3383. if (_hdsaComponent)
  3384. {
  3385. int i;
  3386. for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  3387. {
  3388. COMPONENTA comp;
  3389. comp.dwSize = sizeof(COMPONENTA);
  3390. if (DSA_GetItem(_hdsaComponent, i, &comp) != -1)
  3391. {
  3392. if (!lstrcmpi(comp.szSource, lpszSource))
  3393. {
  3394. *pComp = comp;
  3395. iRet = i;
  3396. break;
  3397. }
  3398. }
  3399. else
  3400. {
  3401. TraceMsg(TF_WARNING, "DS FindComponentIndexByID unable to get a component");
  3402. }
  3403. }
  3404. }
  3405. EXITPROC(2, "DS FindComponentIdBySource=%d", iRet);
  3406. return iRet;
  3407. }
  3408. int CActiveDesktop::_FindComponentIndexByID(DWORD dwID)
  3409. {
  3410. int iRet = -1;
  3411. ENTERPROC(2, "DS FindComponentIndexByID(dwID=%d)", dwID);
  3412. if (_hdsaComponent)
  3413. {
  3414. int i;
  3415. for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  3416. {
  3417. COMPONENTA comp;
  3418. comp.dwSize = sizeof(COMPONENTA);
  3419. if (DSA_GetItem(_hdsaComponent, i, &comp) != -1)
  3420. {
  3421. if (comp.dwID == dwID)
  3422. {
  3423. iRet = i;
  3424. break;
  3425. }
  3426. }
  3427. else
  3428. {
  3429. TraceMsg(TF_WARNING, "DS FindComponentIndexByID unable to get a component");
  3430. }
  3431. }
  3432. }
  3433. EXITPROC(2, "DS FindComponent=%d", iRet);
  3434. return iRet;
  3435. }
  3436. //
  3437. // This function is to be used only in special situations. Given a Url, it finds a component
  3438. // that has the src= pointed to that url. Note that what we have is szSource is something like
  3439. // "c:\foo\bar.bmp"; But, what is passed to this function is "file://c:/foo/bar.htm"
  3440. //
  3441. // Warning: This function does a conversion from Path to Url for every component before
  3442. // comparing with the given Url. This is in-efficient. We do it this way because converting
  3443. // the given Url ,which was converted to url from path, back to Path may not result in the
  3444. // original path. In other words a round-trip from path to Url and back to path may not result
  3445. // in the path that was originally entered by the end-user.
  3446. //
  3447. int CActiveDesktop::_FindComponentBySrcUrl(LPTSTR lpszSrcUrl, COMPONENTA *pComp)
  3448. {
  3449. int iRet = -1;
  3450. ENTERPROC(2, "DS FindComponentBySrcUrl(pComp=%8X)", pComp);
  3451. if (_hdsaComponent)
  3452. {
  3453. int i;
  3454. for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++)
  3455. {
  3456. COMPONENTA comp;
  3457. comp.dwSize = sizeof(COMPONENTA);
  3458. if (DSA_GetItem(_hdsaComponent, i, &comp) != -1)
  3459. {
  3460. TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  3461. LPTSTR lpszUrl = szUrl;
  3462. DWORD dwSize;
  3463. //Convert the szSource to Url
  3464. dwSize = ARRAYSIZE(szUrl);
  3465. if (FAILED(UrlCreateFromPath(comp.szSource, lpszUrl, &dwSize, 0)))
  3466. lpszUrl = comp.szSource;
  3467. if (!lstrcmpi(lpszUrl, lpszSrcUrl))
  3468. {
  3469. *pComp = comp;
  3470. iRet = i;
  3471. break;
  3472. }
  3473. }
  3474. else
  3475. {
  3476. TraceMsg(TF_WARNING, "DS FindComponentBySrcUrl unable to get a component");
  3477. }
  3478. }
  3479. }
  3480. EXITPROC(2, "DS FindComponentBySrcUrl=%d", iRet);
  3481. return iRet;
  3482. }
  3483. HRESULT CActiveDesktop:: GetDesktopItemByID(ULONG_PTR dwID, COMPONENT *pcomp, DWORD dwReserved)
  3484. {
  3485. HRESULT hres = E_FAIL;
  3486. ENTERPROC(1, "DS GetComponentByID(dwID=%d,pcomp=%08X)", dwID, pcomp);
  3487. COMPONENTA CompA;
  3488. ASSERT(!dwReserved); // These should be 0
  3489. // We need to support IE4 apps calling with the old component structure too!
  3490. // We use the size field to detect IE4 v/s newer apps!
  3491. if (!pcomp || ((pcomp->dwSize != sizeof(*pcomp)) && (pcomp->dwSize != sizeof(IE4COMPONENT))))
  3492. return E_INVALIDARG;
  3493. if (pcomp)
  3494. {
  3495. int index = _FindComponentIndexByID((DWORD)dwID);
  3496. if (index != -1)
  3497. {
  3498. if (DSA_GetItem(_hdsaComponent, index, &CompA) != -1)
  3499. {
  3500. hres = S_OK;
  3501. }
  3502. else
  3503. {
  3504. TraceMsg(TF_WARNING, "DS GetComponentByID unable to get component");
  3505. }
  3506. }
  3507. else
  3508. {
  3509. TraceMsg(TF_WARNING, "DS GetComponentByID unable to find component");
  3510. }
  3511. }
  3512. else
  3513. {
  3514. TraceMsg(TF_WARNING, "DS GetComponentByID given NULL pcomp");
  3515. }
  3516. if (SUCCEEDED(hres))
  3517. {
  3518. MultiCompToWideComp(&CompA, pcomp);
  3519. }
  3520. EXITPROC(1, "DS GetComponentByID=%d", hres);
  3521. return hres;
  3522. }
  3523. HRESULT CActiveDesktop::RemoveDesktopItem(LPCCOMPONENT pComp, DWORD dwReserved)
  3524. {
  3525. COMPONENTA CompA, CompToDelete;
  3526. int iIndex;
  3527. HRESULT hres = E_FAIL;
  3528. ASSERT(!dwReserved); // These should be 0
  3529. // We need to support IE4 apps calling with the old component structure too!
  3530. // We use the size field to detect IE4 v/s newer apps!
  3531. if (!pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT))))
  3532. return E_INVALIDARG;
  3533. CompA.dwSize = sizeof(CompA);
  3534. CompToDelete.dwSize = sizeof(CompToDelete);
  3535. //Convert the struct to internal struct.
  3536. ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE);
  3537. // See if the component already exists.
  3538. iIndex = _FindComponentBySource(CompA.szSource, &CompToDelete);
  3539. if (iIndex > -1)
  3540. {
  3541. if (RemoveComponentPrivate(iIndex, &CompToDelete))
  3542. {
  3543. hres = S_OK;
  3544. }
  3545. }
  3546. return(hres);
  3547. }
  3548. BOOL CActiveDesktop::RemoveComponentPrivate(int iIndex, COMPONENTA *pcomp)
  3549. {
  3550. BOOL fRet = FALSE;
  3551. ENTERPROC(1, "DS RemoveComponent(pcomp=%08X)", pcomp);
  3552. if (_hdsaComponent)
  3553. {
  3554. if (iIndex == -1)
  3555. iIndex = _FindComponentIndexByID(pcomp->dwID);
  3556. if (iIndex != -1)
  3557. {
  3558. if (DSA_DeleteItem(_hdsaComponent, iIndex) != -1)
  3559. {
  3560. _fDirty = TRUE;
  3561. fRet = TRUE;
  3562. }
  3563. else
  3564. {
  3565. TraceMsg(TF_WARNING, "DS RemoveComponent could not remove an item");
  3566. }
  3567. }
  3568. else
  3569. {
  3570. TraceMsg(TF_WARNING, "DS RemoveComponent could not find item to remove");
  3571. }
  3572. }
  3573. else
  3574. {
  3575. TraceMsg(TF_WARNING, "DS RemoveComponent has no components to remove");
  3576. }
  3577. EXITPROC(1, "DS RemoveComponent=%d", fRet);
  3578. return fRet;
  3579. }
  3580. HRESULT CActiveDesktop::_CopyComponent(COMPONENTA *pCompDest, COMPONENTA *pCompSrc, DWORD dwFlags)
  3581. {
  3582. HRESULT hrTemp, hr = S_OK;
  3583. //Copy only those elements mentioned in the flag!
  3584. // if (dwFlags & COMP_ELEM_ID)
  3585. // pCompDest->dwID = pCompSrc->dwID;
  3586. if (dwFlags & COMP_ELEM_TYPE)
  3587. pCompDest-> iComponentType = pCompSrc->iComponentType;
  3588. if (dwFlags & COMP_ELEM_CHECKED)
  3589. pCompDest-> fChecked = pCompSrc->fChecked;
  3590. if (dwFlags & COMP_ELEM_DIRTY)
  3591. pCompDest-> fDirty = pCompSrc-> fDirty;
  3592. if (dwFlags & COMP_ELEM_NOSCROLL)
  3593. pCompDest-> fNoScroll = pCompSrc-> fNoScroll;
  3594. if (dwFlags & COMP_ELEM_POS_LEFT)
  3595. pCompDest-> cpPos.iLeft= pCompSrc->cpPos.iLeft;
  3596. if (dwFlags & COMP_ELEM_POS_TOP)
  3597. pCompDest-> cpPos.iTop= pCompSrc->cpPos.iTop;
  3598. if (dwFlags & COMP_ELEM_SIZE_WIDTH)
  3599. pCompDest-> cpPos.dwWidth= pCompSrc->cpPos.dwWidth;
  3600. if (dwFlags & COMP_ELEM_SIZE_HEIGHT)
  3601. pCompDest-> cpPos.dwHeight= pCompSrc->cpPos.dwHeight;
  3602. if (dwFlags & COMP_ELEM_POS_ZINDEX)
  3603. pCompDest-> cpPos.izIndex= pCompSrc->cpPos.izIndex;
  3604. if (dwFlags & COMP_ELEM_SOURCE)
  3605. {
  3606. hrTemp = StringCchCopy(pCompDest->szSource, ARRAYSIZE(pCompDest->szSource), pCompSrc->szSource);
  3607. if (FAILED(hrTemp))
  3608. {
  3609. hr = hrTemp;
  3610. }
  3611. }
  3612. if (dwFlags & COMP_ELEM_FRIENDLYNAME)
  3613. {
  3614. hrTemp = StringCchCopy(pCompDest->szFriendlyName, ARRAYSIZE(pCompDest->szFriendlyName), pCompSrc->szFriendlyName);
  3615. if (FAILED(hrTemp))
  3616. {
  3617. hr = hrTemp;
  3618. }
  3619. }
  3620. if (dwFlags & COMP_ELEM_SUBSCRIBEDURL)
  3621. {
  3622. hrTemp = StringCchCopy(pCompDest->szSubscribedURL, ARRAYSIZE(pCompDest->szSubscribedURL), pCompSrc->szSubscribedURL);
  3623. if (FAILED(hrTemp))
  3624. {
  3625. hr = hrTemp;
  3626. }
  3627. }
  3628. if (dwFlags & COMP_ELEM_ORIGINAL_CSI)
  3629. pCompDest->csiOriginal = pCompSrc->csiOriginal;
  3630. if (dwFlags & COMP_ELEM_RESTORED_CSI)
  3631. {
  3632. pCompDest->csiRestored = pCompSrc->csiRestored;
  3633. // 98/08/21 vtan #174542: When changing csiRestored using the Active
  3634. // Desktop API and the component is zoomed the csiRestored information
  3635. // needs to be copied to the cpPos field as well as this is where the
  3636. // actual information is stored when the component is restored. This
  3637. // is only applicable to the case when the component is zoomed.
  3638. if (ISZOOMED(pCompDest))
  3639. {
  3640. pCompDest->cpPos.iLeft = pCompSrc->csiRestored.iLeft;
  3641. pCompDest->cpPos.iTop = pCompSrc->csiRestored.iTop;
  3642. pCompDest->cpPos.dwWidth = pCompSrc->csiRestored.dwWidth;
  3643. pCompDest->cpPos.dwHeight = pCompSrc->csiRestored.dwHeight;
  3644. }
  3645. }
  3646. if (dwFlags & COMP_ELEM_CURITEMSTATE) // Only allow the modification of the public bits - propagate the internal bits unchanged.
  3647. pCompDest->dwCurItemState = (pCompDest->dwCurItemState & IS_VALIDINTERNALBITS) | (pCompSrc->dwCurItemState & ~IS_VALIDINTERNALBITS);
  3648. return hr;
  3649. }
  3650. HRESULT CActiveDesktop::GetDesktopItemBySource(LPCWSTR lpcwszSource, LPCOMPONENT pComp, DWORD dwFlags)
  3651. {
  3652. COMPONENTA CompNew;
  3653. HRESULT hres = E_FAIL;
  3654. int iIndex;
  3655. //Passing a NULL to SHUnicodeToTChar causes a fault. So, let's fail it.
  3656. if (lpcwszSource == NULL)
  3657. return E_INVALIDARG;
  3658. // We need to support IE4 apps calling with the old component structure too!
  3659. // We use the size field to detect IE4 v/s newer apps!
  3660. if (!pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT))))
  3661. return E_INVALIDARG;
  3662. CompNew.dwSize = sizeof(COMPONENTA);
  3663. SHUnicodeToTChar(lpcwszSource, CompNew.szSource, ARRAYSIZE(CompNew.szSource));
  3664. iIndex = _FindComponentBySource(CompNew.szSource, &CompNew);
  3665. if (iIndex > -1)
  3666. {
  3667. MultiCompToWideComp(&CompNew, pComp);
  3668. hres = S_OK;
  3669. }
  3670. return(hres);
  3671. }
  3672. HRESULT CActiveDesktop::ModifyDesktopItem(LPCCOMPONENT pComp, DWORD dwFlags)
  3673. {
  3674. COMPONENTA CompA, CompNew;
  3675. HRESULT hres = E_FAIL;
  3676. int iIndex = -1;
  3677. // We need to support IE4 apps calling with the old component structure too!
  3678. // We use the size field to detect IE4 v/s newer apps!
  3679. if (!pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT))))
  3680. return E_INVALIDARG;
  3681. CompA.dwSize = sizeof(COMPONENTA);
  3682. CompNew.dwSize = sizeof(COMPONENTA);
  3683. //Convert public param structure to private param structure.
  3684. ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE);
  3685. //See if this component already exists.
  3686. iIndex = _FindComponentBySource(CompA.szSource, &CompNew);
  3687. if (iIndex > -1)
  3688. {
  3689. hres = _CopyComponent(&CompNew, &CompA, dwFlags);
  3690. if (SUCCEEDED(hres))
  3691. {
  3692. if (dwFlags & (COMP_ELEM_POS_LEFT | COMP_ELEM_POS_TOP | COMP_ELEM_SIZE_WIDTH | COMP_ELEM_SIZE_HEIGHT | COMP_ELEM_CHECKED | COMP_ELEM_CURITEMSTATE))
  3693. PositionComponent(&CompNew, &CompNew.cpPos, CompNew.iComponentType, FALSE);
  3694. if (ISZOOMED(&CompNew))
  3695. RestoreComponent(_hdsaComponent, &CompNew);
  3696. CompNew.fDirty = TRUE; //Since the component is modified, we set the dirty bit!
  3697. if (UpdateComponentPrivate(iIndex, &CompNew))
  3698. hres = S_OK;
  3699. }
  3700. }
  3701. return(hres);
  3702. }
  3703. BOOL CActiveDesktop::UpdateComponentPrivate(int iIndex, COMPONENTA *pcomp)
  3704. {
  3705. BOOL fRet = FALSE;
  3706. ENTERPROC(1, "DS UpdateComponentPrivate(pcomp=%08X)", pcomp);
  3707. if (_hdsaComponent)
  3708. {
  3709. if (iIndex == -1)
  3710. iIndex = _FindComponentIndexByID(pcomp->dwID);
  3711. if (iIndex != -1)
  3712. {
  3713. if (DSA_SetItem(_hdsaComponent, iIndex, pcomp) != -1)
  3714. {
  3715. _fDirty = TRUE;
  3716. fRet = TRUE;
  3717. }
  3718. else
  3719. {
  3720. TraceMsg(TF_WARNING, "DS UpdateComponent could not update an item");
  3721. }
  3722. }
  3723. else
  3724. {
  3725. TraceMsg(TF_WARNING, "DS UpdateComponent could not find item to update");
  3726. }
  3727. }
  3728. else
  3729. {
  3730. TraceMsg(TF_WARNING, "DS UpdateComponent has no components to update");
  3731. }
  3732. EXITPROC(1, "DS UpdateComponent=%d", fRet);
  3733. return fRet;
  3734. }
  3735. HRESULT CActiveDesktop::GetDesktopItemCount(LPINT lpiCount, DWORD dwReserved)
  3736. {
  3737. if (!lpiCount)
  3738. return (E_INVALIDARG);
  3739. *lpiCount = 0;
  3740. ENTERPROC(1, "DS GetComponentsCount()");
  3741. ASSERT(!dwReserved); // These should be 0
  3742. if (_hdsaComponent)
  3743. {
  3744. *lpiCount = DSA_GetItemCount(_hdsaComponent);
  3745. }
  3746. EXITPROC(1, "DS GetComponentsCount=%d", *lpiCount);
  3747. return S_OK;
  3748. }
  3749. HRESULT CActiveDesktop::GetDesktopItem(int nComponent, COMPONENT *pComp, DWORD dwReserved)
  3750. {
  3751. COMPONENTA CompA;
  3752. ASSERT(!dwReserved); // These should be 0
  3753. // We need to support IE4 apps calling with the old component structure too!
  3754. // We use the size field to detect IE4 v/s newer apps!
  3755. if ((nComponent < 0) || !pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT))))
  3756. return E_INVALIDARG;
  3757. CompA.dwSize = sizeof(COMPONENTA);
  3758. if (GetComponentPrivate(nComponent, &CompA))
  3759. {
  3760. //Convert the structure to the Public form.
  3761. ConvertCompStruct((COMPONENTA *)pComp, &CompA, FALSE);
  3762. return(S_OK);
  3763. }
  3764. else
  3765. return(E_FAIL);
  3766. }
  3767. BOOL CActiveDesktop::GetComponentPrivate(int nComponent, COMPONENTA *pcomp)
  3768. {
  3769. BOOL fRet = FALSE;
  3770. ENTERPROC(1, "DS GetComponent(nComponent=%d,pcomp=%08X)", nComponent, pcomp);
  3771. if (_hdsaComponent && pcomp && (nComponent < DSA_GetItemCount(_hdsaComponent)))
  3772. {
  3773. if (DSA_GetItem(_hdsaComponent, nComponent, pcomp) != -1)
  3774. {
  3775. fRet = TRUE;
  3776. }
  3777. else
  3778. {
  3779. TraceMsg(TF_WARNING, "DS GetComponent unable to get a component");
  3780. }
  3781. }
  3782. else
  3783. {
  3784. TraceMsg(TF_WARNING, "DS GetComponent does not have a DSA");
  3785. }
  3786. EXITPROC(1, "DS GetComponent=%d", fRet);
  3787. return fRet;
  3788. }
  3789. HRESULT CActiveDesktop::QueryInterface(REFIID riid, LPVOID *ppvObj)
  3790. {
  3791. if (IsEqualIID(riid, IID_IActiveDesktop))
  3792. {
  3793. *ppvObj = (IActiveDesktop *)this;
  3794. _Initialize();
  3795. }
  3796. else if (IsEqualIID(riid, IID_IUnknown))
  3797. {
  3798. *ppvObj = (IActiveDesktop *)this;
  3799. }
  3800. else if (IsEqualIID(riid, IID_IActiveDesktopP))
  3801. {
  3802. *ppvObj = (IActiveDesktopP *)this;
  3803. }
  3804. else if (IsEqualIID(riid, IID_IADesktopP2))
  3805. {
  3806. *ppvObj = (IADesktopP2 *)this;
  3807. }
  3808. else if (IsEqualIID(riid, IID_IPropertyBag))
  3809. {
  3810. *ppvObj = (IPropertyBag *)this;
  3811. }
  3812. else
  3813. {
  3814. *ppvObj = NULL;
  3815. return E_NOINTERFACE;
  3816. }
  3817. AddRef();
  3818. return S_OK;
  3819. }
  3820. // Helper function so that it's easy to create one internally
  3821. // Actually, it's not ver much help any more...
  3822. STDAPI CActiveDesktop_InternalCreateInstance(LPUNKNOWN * ppunk, REFIID riid)
  3823. {
  3824. return CActiveDesktop_CreateInstance(NULL, riid, (void **)ppunk);
  3825. }
  3826. // Our class factory create instance code
  3827. STDAPI CActiveDesktop_CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void **ppvOut)
  3828. {
  3829. TraceMsg(TF_DESKSTAT, "CActiveDesktop- CreateInstance");
  3830. CActiveDesktop *pad = new CActiveDesktop();
  3831. if (pad)
  3832. {
  3833. HRESULT hres = pad->QueryInterface(riid, ppvOut);
  3834. pad->Release();
  3835. return hres;
  3836. }
  3837. *ppvOut = NULL;
  3838. return E_OUTOFMEMORY;
  3839. }
  3840. #ifdef DEBUG
  3841. //
  3842. // FEATURE - Move g_dwDeskStatTrace into ccshell.ini to prevent recompiles.
  3843. //
  3844. DWORD g_dwDeskStatTrace = 2;
  3845. static DWORD g_dwIndent = 0;
  3846. static const TCHAR c_szDotDot[] = TEXT("..");
  3847. #define MAX_INDENTATION_VALUE 0x20
  3848. void EnterProcDS(DWORD dwTraceLevel, LPSTR pszFmt, ...)
  3849. {
  3850. TCHAR szFmt[1000];
  3851. va_list arglist;
  3852. SHAnsiToTChar(pszFmt, szFmt, ARRAYSIZE(szFmt));
  3853. if (dwTraceLevel <= g_dwDeskStatTrace)
  3854. {
  3855. TCHAR szOutput[1000];
  3856. szOutput[0] = TEXT('\0');
  3857. for (DWORD i=0; i<g_dwIndent; i++)
  3858. {
  3859. StringCchCat(szOutput, ARRAYSIZE(szOutput), c_szDotDot); // truncation fine, this is debug spew
  3860. }
  3861. int cchOutput = lstrlen(szOutput);
  3862. va_start(arglist, pszFmt);
  3863. StringCchVPrintf(szOutput + cchOutput, ARRAYSIZE(szOutput) - cchOutput, szFmt, arglist); // truncation fine, this is debug spew
  3864. va_end(arglist);
  3865. TraceMsg(TF_DESKSTAT, "%s", szOutput);
  3866. // We don't want this value to get out of hand because of
  3867. // unmatched Enter and Exit calls in functions (which will
  3868. // trash the stack).
  3869. if (g_dwIndent < MAX_INDENTATION_VALUE)
  3870. g_dwIndent++;
  3871. }
  3872. }
  3873. void ExitProcDS(DWORD dwTraceLevel, LPSTR pszFmt, ...)
  3874. {
  3875. TCHAR szFmt[1000];
  3876. TCHAR szOutput[1000];
  3877. va_list arglist;
  3878. SHAnsiToTChar(pszFmt, szFmt, ARRAYSIZE(szFmt));
  3879. if (dwTraceLevel <= g_dwDeskStatTrace)
  3880. {
  3881. //This can happen if the Enter and Exit procs are unmatched.
  3882. if (g_dwIndent > 0)
  3883. g_dwIndent--;
  3884. szOutput[0] = TEXT('\0');
  3885. for (DWORD i=0; i<g_dwIndent; i++)
  3886. {
  3887. StringCchCat(szOutput, ARRAYSIZE(szOutput), c_szDotDot); // truncation fine, this is debug spew
  3888. }
  3889. int cchOutput = lstrlen(szOutput);
  3890. va_start(arglist, pszFmt);
  3891. StringCchVPrintf(szOutput + cchOutput, ARRAYSIZE(szOutput) - cchOutput, szFmt, arglist); // truncation fine, this is debug spew
  3892. va_end(arglist);
  3893. TraceMsg(TF_DESKSTAT, "%s", szOutput);
  3894. }
  3895. }
  3896. #endif
  3897. /*************************************************************************
  3898. *
  3899. * IActiveDesktopP methods and helper functions
  3900. *
  3901. * IActiveDesktopP is a private interface used to implement helper
  3902. * functionality that is used internally by the various shell binaries.
  3903. *
  3904. * Notes:
  3905. * Getting an interface to IActiveDesktopP does not initialize the state
  3906. * of the object such that member functions are able to call IActiveDesktop
  3907. * member functions. This is so that it is a more lightweight implementation
  3908. * and also simplifies the implementation of SetScheme. If a subsequent QI for
  3909. * IActiveDesktop is performed then it will initialize properly and any member
  3910. * function can then be called.
  3911. *
  3912. *************************************************************************/
  3913. //
  3914. // SetScheme
  3915. //
  3916. // Used to set the current scheme that the object will read and write to
  3917. // when it is initialized. This method must be called before a subsequent
  3918. // QI to IActiveDesktop is made.
  3919. //
  3920. HRESULT CActiveDesktop::SetScheme(LPCWSTR pwszSchemeName, DWORD dwFlags)
  3921. {
  3922. LPTSTR pszSchemeName, pszAlloc;
  3923. int icch;
  3924. // Can't set the local scheme after we've been initialized...we can fix this
  3925. // later if necessary but for now it's simplest this way.
  3926. if (_fInitialized && (dwFlags & SCHEME_LOCAL))
  3927. return E_FAIL;
  3928. // Sanity checks
  3929. if (!pwszSchemeName || ((icch = lstrlenW(pwszSchemeName)) > MAX_PATH - 1))
  3930. return E_INVALIDARG;
  3931. pszSchemeName = (LPTSTR)pwszSchemeName;
  3932. if (dwFlags & SCHEME_CREATE)
  3933. {
  3934. LONG lRet;
  3935. HKEY hkey, hkey2;
  3936. lRet = RegCreateKeyEx(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME_LOCATION, 0, NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkey, NULL);
  3937. if (ERROR_SUCCESS == lRet)
  3938. {
  3939. lRet = RegCreateKeyEx(hkey, pszSchemeName, 0, NULL, 0, KEY_WRITE, NULL, &hkey2, NULL);
  3940. if (ERROR_SUCCESS == lRet)
  3941. {
  3942. RegCloseKey(hkey2);
  3943. }
  3944. RegCloseKey(hkey);
  3945. }
  3946. if (ERROR_SUCCESS != lRet)
  3947. {
  3948. return E_FAIL;
  3949. }
  3950. }
  3951. if (dwFlags & SCHEME_LOCAL)
  3952. {
  3953. // The local case is easy - just copy the string to our local variable,
  3954. // it will be used when IActiveDesktop is initialized.
  3955. if (!(pszAlloc = (LPTSTR)LocalAlloc(LPTR, (icch + 1) * sizeof(TCHAR))))
  3956. return E_OUTOFMEMORY;
  3957. if (_pszScheme)
  3958. LocalFree((HANDLE)_pszScheme);
  3959. _pszScheme = pszAlloc;
  3960. HRESULT hr = StringCchCopy(_pszScheme, icch + 1, pszSchemeName);
  3961. if (FAILED(hr))
  3962. {
  3963. return hr;
  3964. }
  3965. }
  3966. if (dwFlags & SCHEME_GLOBAL)
  3967. {
  3968. // Update the registry with the new global scheme value
  3969. if (dwFlags & SCHEME_DISPLAY)
  3970. SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_DISPLAY,
  3971. REG_SZ, pszSchemeName, CbFromCch(lstrlen(pszSchemeName) + 1));
  3972. if (dwFlags & SCHEME_EDIT)
  3973. SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_EDIT,
  3974. REG_SZ, pszSchemeName, CbFromCch(lstrlen(pszSchemeName) + 1));
  3975. }
  3976. if (dwFlags & (SCHEME_REFRESH | SCHEME_UPDATE))
  3977. {
  3978. DWORD dwUpdateFlags = AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_SAVE;
  3979. if (dwFlags & SCHEME_REFRESH)
  3980. dwUpdateFlags |= (AD_APPLY_REFRESH | AD_APPLY_DYNAMICREFRESH);
  3981. _Initialize();
  3982. _fUseDynamicHtml=FALSE;
  3983. ApplyChanges(dwUpdateFlags);
  3984. }
  3985. return S_OK;
  3986. }
  3987. HRESULT GetGlobalScheme(LPWSTR pwszScheme, LPDWORD lpdwcchBuffer, DWORD dwFlags)
  3988. {
  3989. DWORD cbScheme = *lpdwcchBuffer * sizeof(pwszScheme[0]);
  3990. LONG lret = SHGetValueW(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME,
  3991. (dwFlags & SCHEME_EDIT) ? REG_VAL_SCHEME_EDIT : REG_VAL_SCHEME_DISPLAY, NULL,
  3992. pwszScheme, &cbScheme);
  3993. if (ERROR_SUCCESS == lret)
  3994. {
  3995. *lpdwcchBuffer = lstrlenW(pwszScheme);
  3996. }
  3997. return (lret == ERROR_SUCCESS ? S_OK : E_FAIL);
  3998. }
  3999. //
  4000. // GetScheme
  4001. //
  4002. //
  4003. HRESULT CActiveDesktop::GetScheme(LPWSTR pwszSchemeName, LPDWORD lpdwcchBuffer, DWORD dwFlags)
  4004. {
  4005. // Sanity checks
  4006. if (!pwszSchemeName || *lpdwcchBuffer == 0)
  4007. return E_INVALIDARG;
  4008. if (dwFlags & SCHEME_LOCAL)
  4009. {
  4010. if (!_pszScheme)
  4011. {
  4012. HRESULT hres;
  4013. // Special case if no local scheme has explicitly been selected yet.
  4014. // The default scheme is the global display scheme in this case.
  4015. if (SUCCEEDED(hres = GetGlobalScheme(pwszSchemeName, lpdwcchBuffer, SCHEME_DISPLAY)))
  4016. {
  4017. hres = SetScheme(pwszSchemeName, SCHEME_LOCAL);
  4018. }
  4019. return hres;
  4020. }
  4021. SHTCharToUnicode(_pszScheme, pwszSchemeName, *lpdwcchBuffer);
  4022. *lpdwcchBuffer = lstrlenW(pwszSchemeName);
  4023. return S_OK;
  4024. }
  4025. if (dwFlags & SCHEME_GLOBAL)
  4026. {
  4027. return GetGlobalScheme(pwszSchemeName, lpdwcchBuffer, dwFlags);
  4028. }
  4029. return E_INVALIDARG;
  4030. }
  4031. BOOL UpdateAllDesktopSubscriptions(IADesktopP2 *);
  4032. HRESULT CActiveDesktop::UpdateAllDesktopSubscriptions()
  4033. {
  4034. ::UpdateAllDesktopSubscriptions(this);
  4035. return S_OK;
  4036. }
  4037. void CActiveDesktop::_GenerateHtmlBStrForComp(COMPONENTA *pComp, BSTR *pbstr)
  4038. {
  4039. ENTERPROC(2, "DS _GenerateHtmlBstrForComp");
  4040. if (_pStream = SHCreateMemStream(NULL, 0)) //Create a mem stream.
  4041. {
  4042. LARGE_INTEGER libMove = {0};
  4043. ULARGE_INTEGER libCurPos;
  4044. // Since _pStream is setup, the following call will generate the component HTML into
  4045. // that stream.
  4046. _GenerateHtmlComponent(pComp);
  4047. //Get the size of the stream generated.
  4048. if (SUCCEEDED(_pStream->Seek(libMove, STREAM_SEEK_CUR, &libCurPos)))
  4049. {
  4050. //Allocare a BSTR big enough to hold our component HTML code.
  4051. if (*pbstr = SysAllocStringLen(NULL, (libCurPos.LowPart)/sizeof(WCHAR)))
  4052. {
  4053. _pStream->Seek(libMove, STREAM_SEEK_SET, NULL);
  4054. _pStream->Read(*pbstr, libCurPos.LowPart, NULL);
  4055. }
  4056. }
  4057. //NOTE: The bStr is released by the caller.
  4058. ATOMICRELEASE(_pStream);
  4059. }
  4060. else
  4061. TraceMsg(TF_WARNING, "DS _GenerateHtmlBstrForComp unable to create a mem stream");
  4062. EXITPROC(2, "DS _GenerateHtmlBstrForComp");
  4063. }
  4064. void CActiveDesktop::_UpdateStyleOfElement(IHTMLElement *pElem, LPCOMPONENTA lpCompA)
  4065. {
  4066. IHTMLStyle *pHtmlStyle;
  4067. if (SUCCEEDED(pElem->get_style(&pHtmlStyle)))
  4068. {
  4069. long lPixelVal;
  4070. VARIANT vVal;
  4071. VARIANT vValNew;
  4072. if (SUCCEEDED(pHtmlStyle->get_pixelLeft(&lPixelVal)) && (lPixelVal != lpCompA->cpPos.iLeft))
  4073. {
  4074. TraceMsg(TF_DYNAMICHTML, "iLeft changes from %d to %d", lPixelVal, lpCompA->cpPos.iLeft);
  4075. pHtmlStyle->put_pixelLeft((long)(lpCompA->cpPos.iLeft));
  4076. }
  4077. if (SUCCEEDED(pHtmlStyle->get_pixelTop(&lPixelVal)) && (lPixelVal != lpCompA->cpPos.iTop))
  4078. {
  4079. TraceMsg(TF_DYNAMICHTML, "iTop changes from %d to %d", lPixelVal, lpCompA->cpPos.iTop);
  4080. pHtmlStyle->put_pixelTop((long)(lpCompA->cpPos.iTop));
  4081. }
  4082. VariantInit(&vVal);
  4083. if (SUCCEEDED(pHtmlStyle->get_width(&vVal))) //Get the width as BSTR to see if width attribute exists
  4084. {
  4085. //See if the width attribute exists now.
  4086. if ((vVal.vt == VT_BSTR) && (vVal.bstrVal == NULL))
  4087. {
  4088. // Width attribute does not exist for this element; This means that
  4089. // this element has the default width (may be a picture shown in it's original width).
  4090. if (lpCompA->cpPos.dwWidth != COMPONENT_DEFAULT_WIDTH)
  4091. {
  4092. //Component's new width is different from the default width. So, set the new width.
  4093. TraceMsg(TF_DYNAMICHTML, "dwWidth changes from default to %d", lpCompA->cpPos.dwWidth);
  4094. pHtmlStyle->put_pixelWidth((long)(lpCompA->cpPos.dwWidth));
  4095. }
  4096. //else, nothing to do! (the widths match exactly).
  4097. }
  4098. else
  4099. {
  4100. // Width attribute exists! That means that this element has a width other than the
  4101. // default width.
  4102. // See if the new width is the default width.
  4103. if (lpCompA->cpPos.dwWidth == COMPONENT_DEFAULT_WIDTH)
  4104. {
  4105. // The old width is NOT default; But, the new width is default. So, let's just
  4106. // remove the width attribute.
  4107. VariantInit(&vValNew);
  4108. vValNew.vt = VT_BSTR;
  4109. vValNew.bstrVal = NULL;
  4110. pHtmlStyle->put_width(vValNew);
  4111. VariantClear(&vValNew);
  4112. }
  4113. else
  4114. {
  4115. //Get the existing width in pixels.
  4116. if (SUCCEEDED(pHtmlStyle->get_pixelWidth(&lPixelVal)) && (((DWORD)lPixelVal) != lpCompA->cpPos.dwWidth))
  4117. {
  4118. TraceMsg(TF_DYNAMICHTML, "dwWidth changes from %d to %d", lPixelVal, lpCompA->cpPos.dwWidth);
  4119. pHtmlStyle->put_pixelWidth((long)(lpCompA->cpPos.dwWidth));
  4120. }
  4121. //else, nothing else to do because the widths match!
  4122. }
  4123. }
  4124. VariantClear(&vVal);
  4125. }
  4126. if (SUCCEEDED(pHtmlStyle->get_height(&vVal))) //Get the height as BSTR to see if height attribute exists
  4127. {
  4128. // See if the height attribute exists.
  4129. if ((vVal.vt == VT_BSTR) && (vVal.bstrVal == NULL))
  4130. {
  4131. // Height attribute does not exist for this element; This means that
  4132. // this element has the default height (may be a picture shown in it's original height).
  4133. if (lpCompA->cpPos.dwHeight != COMPONENT_DEFAULT_HEIGHT)
  4134. {
  4135. //Component's new height is different from the default height. So, set the new height.
  4136. TraceMsg(TF_DYNAMICHTML, "dwHeight changes from default to %d", lpCompA->cpPos.dwHeight);
  4137. pHtmlStyle->put_pixelHeight((long)(lpCompA->cpPos.dwHeight));
  4138. }
  4139. //else, nothing to do! (the heights match exactly).
  4140. }
  4141. else
  4142. {
  4143. // Height attribute exists! That means that this element has a height other than the
  4144. // default height.
  4145. // See if the new height is the default height.
  4146. if (lpCompA->cpPos.dwHeight == COMPONENT_DEFAULT_HEIGHT)
  4147. {
  4148. // The old height is NOT default; But, the new height is default. So, let's just
  4149. // remove the height attribute.
  4150. VariantInit(&vValNew);
  4151. vValNew.vt = VT_BSTR;
  4152. vValNew.bstrVal = NULL;
  4153. pHtmlStyle->put_height(vValNew); //remove the height attribute!
  4154. VariantClear(&vValNew);
  4155. }
  4156. else
  4157. {
  4158. //Get the existing height in pixels and see if it is different.
  4159. if (SUCCEEDED(pHtmlStyle->get_pixelHeight(&lPixelVal)) && (((DWORD)lPixelVal) != lpCompA->cpPos.dwHeight))
  4160. {
  4161. //Since the new height is different, let's use set the new height!
  4162. TraceMsg(TF_DYNAMICHTML, "dwHeight changes from %d to %d", lPixelVal, lpCompA->cpPos.dwHeight);
  4163. pHtmlStyle->put_pixelHeight((long)(lpCompA->cpPos.dwHeight));
  4164. }
  4165. //else, nothing else to do because the heights match!
  4166. }
  4167. }
  4168. VariantClear(&vVal);
  4169. }
  4170. if (SUCCEEDED(pHtmlStyle->get_zIndex(&vVal)) && (vVal.vt == VT_I4) && (vVal.lVal != lpCompA->cpPos.izIndex))
  4171. {
  4172. TraceMsg(TF_DYNAMICHTML, "ZIndex changes from %d to %d", vVal.lVal, lpCompA->cpPos.izIndex);
  4173. vVal.lVal = lpCompA->cpPos.izIndex;
  4174. pHtmlStyle->put_zIndex(vVal);
  4175. }
  4176. VariantClear(&vVal);
  4177. pHtmlStyle->Release();
  4178. }
  4179. //FEATURE: Should we check for and set the other attributes like "resizeable" etc.,?
  4180. }
  4181. BOOL CActiveDesktop::_UpdateIdOfElement(IHTMLElement *pElem, LPCOMPONENTA lpCompA)
  4182. {
  4183. BSTR bstrId;
  4184. BOOL fWholeElementReplaced = FALSE; //Assume that the item id does not change.
  4185. //Check if the Id of the component and the element matches.
  4186. if (SUCCEEDED(pElem->get_id(&bstrId))) //get the old id
  4187. {
  4188. if (((DWORD)StrToIntW(bstrId)) != lpCompA->dwID)
  4189. {
  4190. // The following technic does not work in some versions of MSHTML.DLL
  4191. // because IHTMLElement->put_id() does not work unless the doc
  4192. // is in "design mode".
  4193. TCHAR szNewId[MAXID_LENGTH];
  4194. BSTR bstrNewId;
  4195. HRESULT hr = StringCchPrintf(szNewId, ARRAYSIZE(szNewId), TEXT("%d"), lpCompA->dwID);
  4196. if (SUCCEEDED(hr))
  4197. {
  4198. #ifdef DEBUG
  4199. {
  4200. TCHAR szOldId[MAXID_LENGTH];
  4201. if (SUCCEEDED(StringCchPrintf(szOldId, ARRAYSIZE(szOldId), TEXT("%d"), StrToIntW(bstrId))))
  4202. {
  4203. TraceMsg(TF_DYNAMICHTML, "DHTML: Id changes from %s to %s", szOldId, szNewId);
  4204. }
  4205. }
  4206. #endif //DEBUG
  4207. //The Ids do not match. So, let's set the new ID.
  4208. if (bstrNewId = SysAllocStringT(szNewId))
  4209. {
  4210. hr = pElem->put_id(bstrNewId);
  4211. SysFreeString(bstrNewId);
  4212. }
  4213. if (FAILED(hr))
  4214. {
  4215. //Replace the whole element's HTML with the newly generated HTML
  4216. BSTR bstrComp = 0;
  4217. _GenerateHtmlBStrForComp(lpCompA, &bstrComp);
  4218. if (bstrComp)
  4219. {
  4220. if (FAILED(hr = pElem->put_outerHTML(bstrComp)))
  4221. TraceMsg(TF_DYNAMICHTML, "DHTML: put_outerHTML failed");
  4222. fWholeElementReplaced = TRUE;
  4223. SysFreeString(bstrComp);
  4224. }
  4225. else
  4226. {
  4227. AssertMsg(FALSE, TEXT("DHTML: Unable to create html for comp"));
  4228. }
  4229. }
  4230. }
  4231. }
  4232. //else the ids match; nothing to do!
  4233. SysFreeString(bstrId); //free the old id.
  4234. }
  4235. else
  4236. {
  4237. AssertMsg(FALSE, TEXT("DS Unable to get the id of the element"));
  4238. }
  4239. return fWholeElementReplaced;
  4240. }
  4241. HRESULT CActiveDesktop::_UpdateHtmlElement(IHTMLElement *pElem)
  4242. {
  4243. VARIANT vData;
  4244. TCHAR szUrl[INTERNET_MAX_URL_LENGTH];
  4245. TCHAR szSrcPath[INTERNET_MAX_URL_LENGTH];
  4246. LPTSTR lpszSrcPath;
  4247. COMPONENTA CompA;
  4248. int iIndex;
  4249. //If all components are disabled, then we nuke this component from HTML page.
  4250. if (!_co.fEnableComponents)
  4251. {
  4252. TraceMsg(TF_DYNAMICHTML, "DHTML: No item shown in this mode; so, deleting items");
  4253. pElem->put_outerHTML((BSTR)s_sstrEmpty.wsz);
  4254. return S_OK; //Nothing else to do!
  4255. }
  4256. VariantInit(&vData);
  4257. //First determine if the given element is currently a desktop item. (It could have been deleted)
  4258. //Get the element's "src" attribute.
  4259. if (FAILED(pElem->getAttribute((BSTR)s_sstrSRCMember.wsz, VARIANT_FALSE, &vData)) ||
  4260. (vData.vt == VT_NULL) ||
  4261. (vData.bstrVal == NULL))
  4262. {
  4263. //If the subscribed_url is not present, then it could be an object with a classid.
  4264. if (FAILED(pElem->getAttribute((BSTR)s_sstrclassid.wsz, VARIANT_FALSE, &vData)) ||
  4265. (vData.vt == VT_NULL))
  4266. {
  4267. //This element is does not have "src=" or "classid=" attributes. How did this ever
  4268. // become a desktop item with "name=deskmovr" or "name=deskmovrw"?? Hmmmmmm....!!!
  4269. #ifdef DEBUG
  4270. {
  4271. BSTR bstrHtmlForElem;
  4272. // Get the HTML corresponding to the element that does not have a subscribed URL
  4273. if (SUCCEEDED(pElem->get_outerHTML(&bstrHtmlForElem)))
  4274. {
  4275. TraceMsg(TF_DYNAMICHTML, "DHTML: Rogue element: %s", bstrHtmlForElem);
  4276. SysFreeString(bstrHtmlForElem);
  4277. }
  4278. }
  4279. TraceMsg(TF_WARNING, "DHTML: Unable to get the subscribed_url or classid");
  4280. #endif
  4281. //Since this element does not seem to be a valid desktop item, let's nuke it!
  4282. pElem->put_outerHTML((BSTR)s_sstrEmpty.wsz); //delete this element.
  4283. return (E_FAIL); //Nothing else to for this element! It's gone!!!
  4284. }
  4285. if ((vData.vt == VT_NULL) || (vData.bstrVal == NULL))
  4286. return E_FAIL;
  4287. ASSERT(vData.vt == VT_BSTR);
  4288. ASSERT(StrCmpNW(vData.bstrVal, L"clsid:", lstrlen(TEXT("clsid:"))) == 0);
  4289. SHUnicodeToTChar(vData.bstrVal + lstrlen(TEXT("clsid:")), szUrl, ARRAYSIZE(szUrl));
  4290. lpszSrcPath = szUrl; //For classid, the SrcPath and the Url are the same.
  4291. }
  4292. else
  4293. {
  4294. DWORD dwSize;
  4295. if (vData.bstrVal == NULL)
  4296. return (E_FAIL);
  4297. ASSERT(vData.vt == VT_BSTR);
  4298. SHUnicodeToTChar(vData.bstrVal, szUrl, ARRAYSIZE(szUrl));
  4299. dwSize = ARRAYSIZE(szSrcPath);
  4300. lpszSrcPath = szSrcPath;
  4301. if (FAILED(PathCreateFromUrl(szUrl, lpszSrcPath, &dwSize, 0)))
  4302. {
  4303. lpszSrcPath = szUrl;
  4304. }
  4305. }
  4306. VariantClear(&vData); //We made a TCHAR copy above. So, ok to free this.
  4307. CompA.dwSize = sizeof(CompA);
  4308. // First use the Source path to Find the component; This is much more efficient because it
  4309. // involves no conversion from Path to Url and vice-versa.
  4310. if ((iIndex = _FindComponentBySource(lpszSrcPath, &CompA)) < 0)
  4311. {
  4312. // Could not find component using SrcPath!
  4313. // Let's try using the SrcUrl; This is less efficient.
  4314. iIndex = _FindComponentBySrcUrl(szUrl, &CompA);
  4315. }
  4316. if ((iIndex>= 0) && (CompA.fChecked))
  4317. {
  4318. //The component is found and it is enabled.
  4319. TraceMsg(TF_DYNAMICHTML, "DHTML:Updating desktop item with URL: %s", szUrl);
  4320. // If the id changes, we replace the whole HTML for that element, so, no need to check for
  4321. // the individual styles.
  4322. if (!_UpdateIdOfElement(pElem, &CompA))
  4323. _UpdateStyleOfElement(pElem, &CompA);
  4324. CompA.fDirty = TRUE; //Mark the component sothat we know that it had been updated.
  4325. UpdateComponentPrivate(iIndex, &CompA);
  4326. }
  4327. else
  4328. {
  4329. ASSERT((iIndex == -1) || (!CompA.fChecked)); //Component not found OR it is disabled!
  4330. TraceMsg(TF_DYNAMICHTML, "DHTML: Deleting desktop item with URL: %s, SrcPath:%s", szUrl, lpszSrcPath);
  4331. //The component is not present now. So, delete this element from the html page.
  4332. pElem->put_outerHTML((BSTR)s_sstrEmpty.wsz);
  4333. }
  4334. return S_OK;
  4335. }
  4336. //
  4337. // This code enumerates and then updates all the desktop item elements in the active desktop based
  4338. // on the current status of the active desktop items in the CActiveDesktop object (The current
  4339. // status is initialized by reading from the registry when ActiveDesktop object is initialized).
  4340. //
  4341. HRESULT CActiveDesktop::_UpdateDesktopItemHtmlElements(IHTMLDocument2 *pDoc)
  4342. {
  4343. HRESULT hres = S_OK;
  4344. IHTMLElementCollection *pAllElements;
  4345. TraceMsg(TF_DYNAMICHTML, "DHTML: Updating Desktop html elements dynamically");
  4346. if (!_fInitialized) //If not yet initialized, initialize now because we need _co.fEnableComponents.
  4347. _Initialize();
  4348. // We need to check for a change in the background color only if there is no wallpaper or
  4349. // the wallpaper is a picture.
  4350. if (IsWallpaperPicture(_szSelectedWallpaper))
  4351. {
  4352. COLORREF rgbDesktop;
  4353. TCHAR szRgbDesktop[10];
  4354. VARIANT vColor;
  4355. //Check to see if the background color has changed
  4356. rgbDesktop = GetSysColor(COLOR_DESKTOP);
  4357. hres = StringCchPrintf(szRgbDesktop, ARRAYSIZE(szRgbDesktop),
  4358. TEXT("#%02lx%02lx%02lx"), GetRValue(rgbDesktop), GetGValue(rgbDesktop), GetBValue(rgbDesktop));
  4359. if (SUCCEEDED(hres))
  4360. {
  4361. hres = pDoc->get_bgColor(&vColor);
  4362. if (SUCCEEDED(hres) && (vColor.vt == VT_BSTR))
  4363. {
  4364. BSTR bstrNewBgColor = SysAllocStringT(szRgbDesktop);
  4365. //Compare the new and the old strings.
  4366. if (StrCmpW(vColor.bstrVal, bstrNewBgColor))
  4367. {
  4368. BSTR bstrOldBgColor = vColor.bstrVal; //Save the old bstr.
  4369. //So, the colors are different. Set the new color.
  4370. vColor.bstrVal = bstrNewBgColor;
  4371. bstrNewBgColor = bstrOldBgColor; //Set it here sothat it is freed later.
  4372. if (FAILED(pDoc->put_bgColor(vColor)))
  4373. {
  4374. TraceMsg(TF_DYNAMICHTML, "DHTML: Unable to change the background color");
  4375. }
  4376. }
  4377. if (bstrNewBgColor)
  4378. SysFreeString(bstrNewBgColor);
  4379. VariantClear(&vColor);
  4380. }
  4381. }
  4382. }
  4383. //Get a collection of All elements in the Document
  4384. if (SUCCEEDED(hres))
  4385. {
  4386. hres = pDoc->get_all(&pAllElements);
  4387. if (SUCCEEDED(hres))
  4388. {
  4389. VARIANT vName, vIndex;
  4390. IDispatch *pDisp;
  4391. int i;
  4392. long lItemsEnumerated = 0;
  4393. long lLength = 0;
  4394. #ifdef DEBUG
  4395. pAllElements->get_length(&lLength);
  4396. TraceMsg(TF_DYNAMICHTML, "DHTML: Length of All elements:%d", lLength);
  4397. #endif
  4398. for(i = 0; i <= 1; i++)
  4399. {
  4400. //Collect all the elements that have the name="DeskMovr" and then name="DeskMovrW"
  4401. vName.vt = VT_BSTR;
  4402. vName.bstrVal = (BSTR)((i == 0) ? s_sstrDeskMovr.wsz : s_sstrDeskMovrW.wsz);
  4403. VariantInit(&vIndex); //We want to get all elements. So, vIndex is set to VT_EMPTY
  4404. if (SUCCEEDED(pAllElements->item(vName, vIndex, &pDisp)) && pDisp) //Collect all elements we want
  4405. {
  4406. IHTMLElementCollection *pDeskCollection;
  4407. if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLElementCollection, (void **)&pDeskCollection)))
  4408. {
  4409. IUnknown *pUnk;
  4410. IEnumVARIANT *pEnumVar;
  4411. if (SUCCEEDED(pDeskCollection->get_length(&lLength))) //Number of elements.
  4412. lItemsEnumerated += lLength; //Total number of items enumerated.
  4413. TraceMsg(TF_DYNAMICHTML, "DHTML: Enumerated %d number of elements", lLength);
  4414. //Get the enumerator
  4415. if (SUCCEEDED(pDeskCollection->get__newEnum(&pUnk)))
  4416. {
  4417. if (SUCCEEDED(pUnk->QueryInterface(IID_IEnumVARIANT, (void **)&pEnumVar)))
  4418. {
  4419. VARIANT vElem;
  4420. long lEnumCount = 0;
  4421. DWORD cElementsFetched;
  4422. while(SUCCEEDED(pEnumVar->Next(1, &vElem, &cElementsFetched)) && (cElementsFetched == 1))
  4423. {
  4424. IHTMLElement *pElem;
  4425. lEnumCount++;
  4426. // Access the element from the variant.....!
  4427. if ((vElem.vt == VT_DISPATCH) && SUCCEEDED(vElem.pdispVal->QueryInterface(IID_IHTMLElement, (void **)&pElem)))
  4428. {
  4429. _UpdateHtmlElement(pElem); //Update the desktop element's attributes.
  4430. pElem->Release();
  4431. }
  4432. VariantClear(&vElem);
  4433. }
  4434. //Number of items enumerated must be the same as the length
  4435. ASSERT(lEnumCount == lLength);
  4436. pEnumVar->Release();
  4437. }
  4438. pUnk->Release();
  4439. }
  4440. pDeskCollection->Release();
  4441. }
  4442. else
  4443. {
  4444. IHTMLElement *pElem;
  4445. // The QI(IID_IHTMLElementCollection) has failed. It may be because only one item
  4446. // was returned rather than a collection.
  4447. if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLElement, (void **)&pElem)))
  4448. {
  4449. _UpdateHtmlElement(pElem); //Update the desktop element's attributes.
  4450. pElem->Release();
  4451. }
  4452. else
  4453. TraceMsg(TF_WARNING, "DHTML: Unable to get a collection or a single element");
  4454. }
  4455. pDisp->Release();
  4456. }
  4457. } // for loop enumeating "DeskMovr" and "DeskMovrW" items.
  4458. pAllElements->Release();
  4459. }
  4460. }
  4461. // All the elements already present in the Doc have been updated. Now, let's add the
  4462. // new elements, if any.
  4463. if (_co.fEnableComponents)
  4464. _InsertNewDesktopItems(pDoc);
  4465. else
  4466. {
  4467. TraceMsg(TF_DYNAMICHTML, "DHTML: No components are to be shown in this mode;");
  4468. }
  4469. return hres;
  4470. }
  4471. HRESULT CActiveDesktop::_InsertNewDesktopItems(IHTMLDocument2 *pDoc)
  4472. {
  4473. IHTMLElement *pBody;
  4474. if (SUCCEEDED(pDoc->get_body(&pBody)))
  4475. {
  4476. if (_hdsaComponent)
  4477. {
  4478. int i, iCount;
  4479. iCount = DSA_GetItemCount(_hdsaComponent);
  4480. for (i=0; i<iCount; i++)
  4481. {
  4482. COMPONENTA comp;
  4483. comp.dwSize = sizeof(comp);
  4484. if (DSA_GetItem(_hdsaComponent, i, &comp) != -1)
  4485. {
  4486. //Check if this is a newly added component AND it is enabled.
  4487. if ((!comp.fDirty) && comp.fChecked)
  4488. {
  4489. TraceMsg(TF_DYNAMICHTML, "DHTML: Inserted comp: %s", comp.szSource);
  4490. //Yup! This is a newly added component!
  4491. BSTR bstrComp = 0;
  4492. //This is a new component. Generate the HTML for the component.
  4493. _GenerateHtmlBStrForComp(&comp, &bstrComp);
  4494. //Insert the component.
  4495. pBody->insertAdjacentHTML((BSTR)s_sstrBeforeEnd.wsz, (BSTR)bstrComp);
  4496. //Free the string.
  4497. SysFreeString(bstrComp);
  4498. }
  4499. }
  4500. else
  4501. {
  4502. TraceMsg(TF_WARNING, "DHTML: InsertNewComp: Unable to get component %d.", i);
  4503. }
  4504. }
  4505. }
  4506. pBody->Release();
  4507. }
  4508. return S_OK;
  4509. }
  4510. //
  4511. // This function takes a pointer to the ActiveDesktop's ole obj, reads all the changes to be done
  4512. // from the registry and makes those changes to the various elements through dynamic HTML interfaces.
  4513. //
  4514. HRESULT CActiveDesktop::MakeDynamicChanges(IOleObject *pOleObj)
  4515. {
  4516. IHTMLDocument2 *pDoc;
  4517. HRESULT hres = E_FAIL;
  4518. ENTERPROC(2, "MakeDynamicChanges");
  4519. if (pOleObj && SUCCEEDED(pOleObj->QueryInterface(IID_IHTMLDocument2, (void **)&pDoc)))
  4520. {
  4521. // Enumerate all the active desktop components and ensure they are up to date.
  4522. _UpdateDesktopItemHtmlElements(pDoc);
  4523. pDoc->Release();
  4524. }
  4525. else
  4526. {
  4527. TraceMsg(TF_WARNING, "DHTML: MakeDynamicChanges: Unable to get IHTMLDocument2");
  4528. }
  4529. EXITPROC(2, "MakeDynamicChanges");
  4530. return(hres);
  4531. }
  4532. //
  4533. // SetSafeMode
  4534. //
  4535. // Either puts the active desktop in safemode or restores it to the previous
  4536. // scheme before safemode was entered.
  4537. //
  4538. HRESULT CActiveDesktop::SetSafeMode(DWORD dwFlags)
  4539. {
  4540. //
  4541. // Make sure we are in active desktop mode.
  4542. //
  4543. SHELLSTATE ss = {0};
  4544. BOOL fSetSafeMode = (dwFlags & SSM_SET) != 0;
  4545. SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  4546. if (ss.fDesktopHTML)
  4547. {
  4548. //
  4549. // All we need to do is switch the "display" scheme to "safemode" in order to
  4550. // go into safemode. To go out, we just switch the "display" scheme back to the
  4551. // previous "edit" scheme.
  4552. //
  4553. WCHAR wszEdit[MAX_PATH];
  4554. WCHAR wszDisplay[MAX_PATH];
  4555. DWORD dwcch = MAX_PATH;
  4556. if (SUCCEEDED(GetScheme(wszEdit, &dwcch, SCHEME_GLOBAL | SCHEME_EDIT)))
  4557. {
  4558. dwcch = MAX_PATH;
  4559. if (SUCCEEDED(GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY)))
  4560. {
  4561. BOOL fInSafeMode = (StrCmpW(wszDisplay, REG_DESKCOMP_SAFEMODE_SUFFIX_L) == 0);
  4562. if (fSetSafeMode != fInSafeMode)
  4563. {
  4564. LPWSTR lpwstr;
  4565. DWORD dwSchemeFlags = SCHEME_GLOBAL | SCHEME_DISPLAY;
  4566. if (dwFlags & SSM_REFRESH)
  4567. dwSchemeFlags |= SCHEME_REFRESH;
  4568. if (dwFlags & SSM_UPDATE)
  4569. dwSchemeFlags |= SCHEME_UPDATE;
  4570. lpwstr = fSetSafeMode ? REG_DESKCOMP_SAFEMODE_SUFFIX_L : wszEdit;
  4571. SetScheme(lpwstr, dwSchemeFlags);
  4572. }
  4573. }
  4574. }
  4575. }
  4576. return S_OK;
  4577. }
  4578. //
  4579. // EnsureUpdateHTML
  4580. //
  4581. // Ensures that the current html file present on the disk is in sync
  4582. // with the registry information for the current active desktop scheme. If
  4583. // it is not in sync then a fresh copy of the file is generated from the
  4584. // registry for the current scheme.
  4585. //
  4586. HRESULT CActiveDesktop::EnsureUpdateHTML(void)
  4587. {
  4588. DWORD dwFlags = 0;
  4589. DWORD dwDataLength = sizeof(DWORD);
  4590. LONG lRet;
  4591. TCHAR szDeskcomp[MAX_PATH];
  4592. TCHAR szDesktopFile[MAX_PATH];
  4593. DWORD dwRestrictUpdate;
  4594. DWORD dwRestrict = SHRestricted2W(REST_NoChannelUI, NULL, 0);
  4595. DWORD dwSize = sizeof(dwRestrictUpdate);
  4596. BOOL fComponentsDirty = FALSE; //Assume that the components are NOT dirty!
  4597. DWORD dwVersion;
  4598. DWORD dwMinorVersion;
  4599. BOOL fStaleInfoInReg = FALSE;
  4600. BOOL fComponentsZoomDirty = FALSE;
  4601. static BOOL s_fNoDeskComp = (BOOL)-1;
  4602. static BOOL s_fNoWallpaper = (BOOL)-1;
  4603. BOOL fNoDeskComp = SHRestricted(REST_NODESKCOMP);
  4604. BOOL fNoWallpaper = SHRestricted(REST_NOHTMLWALLPAPER);
  4605. BOOL fAdminComponent = FALSE;
  4606. HKEY hkey = NULL;
  4607. HKEY hkeyTime;
  4608. FILETIME ftAdminCompKey;
  4609. if (ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, REG_DESKCOMP_COMPONENTS_ROOT, REG_VAL_GENERAL_RESTRICTUPDATE, NULL, &dwRestrictUpdate, &dwSize))
  4610. {
  4611. dwRestrictUpdate = 0;
  4612. }
  4613. GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_COMPONENTS, NULL);
  4614. //See if this branch of registry is old
  4615. if ((lRet = SHGetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_COMP_VERSION, NULL,
  4616. &dwVersion, &dwDataLength)) == ERROR_SUCCESS)
  4617. {
  4618. if (dwVersion < CUR_DESKHTML_VERSION)
  4619. {
  4620. fStaleInfoInReg = TRUE;
  4621. }
  4622. else
  4623. {
  4624. //Major versions are equal. Check minor versions.
  4625. if ((lRet = SHGetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_COMP_MINOR_VERSION, NULL,
  4626. &dwMinorVersion, &dwDataLength)) == ERROR_SUCCESS)
  4627. {
  4628. if (dwMinorVersion != CUR_DESKHTML_MINOR_VERSION)
  4629. fStaleInfoInReg = TRUE;
  4630. }
  4631. else
  4632. {
  4633. fStaleInfoInReg = TRUE;
  4634. }
  4635. }
  4636. }
  4637. else
  4638. {
  4639. fStaleInfoInReg = TRUE;
  4640. }
  4641. dwDataLength = sizeof(DWORD);
  4642. //Check the dirty bit to see if we need to re-generate the desktop html
  4643. if ((lRet = SHGetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_COMP_GENFLAGS, NULL,
  4644. &dwFlags, &dwDataLength)) == ERROR_SUCCESS)
  4645. {
  4646. if (IsFlagSet(dwFlags, COMPONENTS_DIRTY))
  4647. fComponentsDirty = TRUE;
  4648. if (IsFlagSet(dwFlags, COMPONENTS_ZOOMDIRTY))
  4649. fComponentsZoomDirty = TRUE;
  4650. }
  4651. // See if we need to add/delete an administrator added desktop component now
  4652. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REG_DESKCOMP_ADMINCOMP_ROOT, 0, KEY_READ, &hkey))
  4653. {
  4654. FILETIME ftLast;
  4655. DWORD cbData = sizeof(ftLast);
  4656. DWORD dwType;
  4657. ZeroMemory(&ftLast, sizeof(ftLast));
  4658. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REG_DESKCOMP, 0, KEY_READ, &hkeyTime))
  4659. {
  4660. SHQueryValueEx(hkeyTime, TEXT("LastSyncedTime"), NULL, &dwType, (LPBYTE)&ftLast, &cbData);
  4661. RegCloseKey(hkeyTime);
  4662. }
  4663. RegQueryInfoKey(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ftAdminCompKey);
  4664. if (CompareFileTime(&ftAdminCompKey, &ftLast) == 1) {
  4665. WCHAR wszDisplay[MAX_PATH];
  4666. DWORD dwcch = MAX_PATH;
  4667. if (FAILED(GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY)) ||
  4668. (StrCmpW(wszDisplay, REG_DESKCOMP_SAFEMODE_SUFFIX_L) != 0))
  4669. {
  4670. // We're not in safe mode, it's OK to add the components
  4671. fAdminComponent = TRUE;
  4672. }
  4673. }
  4674. }
  4675. // 99/03/23 #237632 vtan: If the monitor arrangement has been changed from underneath
  4676. // the user (perhaps by another user) then make sure that the components are in valid
  4677. // positions. If not then snap them back into the visible space and mark them as dirty
  4678. // so that the desktop.htt file is regenerated.
  4679. _Initialize();
  4680. if (_hdsaComponent)
  4681. {
  4682. int i, iComponentCount;;
  4683. iComponentCount = DSA_GetItemCount(_hdsaComponent);
  4684. for (i = 0; i < iComponentCount; ++i)
  4685. {
  4686. COMPONENTA *pComponent;
  4687. pComponent = reinterpret_cast<COMPONENTA*>(DSA_GetItemPtr(_hdsaComponent, i));
  4688. if (pComponent != NULL)
  4689. {
  4690. BOOL bChangedPosition = FALSE, bChangedSize = FALSE;
  4691. if (!SHIsTempDisplayMode()) //Modify the positions only if we are not in a temp mode change.
  4692. ValidateComponentPosition(&pComponent->cpPos, pComponent->dwCurItemState, pComponent->iComponentType, &bChangedPosition, &bChangedSize);
  4693. if (bChangedPosition || bChangedSize)
  4694. {
  4695. TBOOL(UpdateComponentPrivate(i, pComponent));
  4696. fComponentsDirty = TRUE;
  4697. }
  4698. }
  4699. }
  4700. }
  4701. if (FAILED(GetPerUserFileName(szDesktopFile, ARRAYSIZE(szDesktopFile), DESKTOPHTML_FILENAME)))
  4702. {
  4703. szDesktopFile[0] = 0;
  4704. }
  4705. if (fComponentsDirty ||
  4706. fComponentsZoomDirty ||
  4707. fStaleInfoInReg ||
  4708. fAdminComponent ||
  4709. fNoDeskComp != s_fNoDeskComp ||
  4710. fNoWallpaper != s_fNoWallpaper ||
  4711. (dwRestrictUpdate != dwRestrict) ||
  4712. !PathFileExistsAndAttributes(szDesktopFile, NULL)) //See if the file exists!
  4713. {
  4714. // Clear out any html wallpaper if it exists and the restriction is set
  4715. if (fNoWallpaper != s_fNoWallpaper)
  4716. {
  4717. if (fNoWallpaper && !IsWallpaperPicture(_szSelectedWallpaper))
  4718. SetWallpaper(L"", 0);
  4719. s_fNoWallpaper = fNoWallpaper;
  4720. }
  4721. // Disable components if the restriction is set
  4722. if (fNoDeskComp != s_fNoDeskComp)
  4723. {
  4724. // We can't set fEnableComponents to FALSE because there is no way via the UI
  4725. // for the user to turn it back on again if the restriction is lifted. Instead we add
  4726. // special case code to _GenerateHtml that checks the restriction too.
  4727. // _co.fEnableComponents = !fNoDeskComp;
  4728. s_fNoDeskComp = fNoDeskComp;
  4729. }
  4730. if (fAdminComponent)
  4731. {
  4732. COMPONENT comp;
  4733. TCHAR pszAdminComp[INTERNET_MAX_URL_LENGTH];
  4734. CHAR szUrl[INTERNET_MAX_URL_LENGTH];
  4735. CHAR * pszUrl;
  4736. CHAR * pszUrlList;
  4737. TCHAR * aszAdminComp[] = {REG_VAL_ADMINCOMP_ADD, REG_VAL_ADMINCOMP_DELETE, NULL};
  4738. int i = 0;
  4739. comp.dwSize = sizeof(comp);
  4740. comp.dwCurItemState = IS_SPLIT | IS_ADJUSTLISTVIEW;
  4741. while (aszAdminComp[i])
  4742. {
  4743. dwDataLength = sizeof(pszAdminComp);
  4744. // The reg value contains an array of space separated urls - currently we support adding and deleting
  4745. // a desktop item via this mechanism.
  4746. if (SHQueryValueEx(hkey, aszAdminComp[i], NULL, NULL, (LPBYTE)pszAdminComp, &dwDataLength) == ERROR_SUCCESS)
  4747. {
  4748. SHTCharToAnsi(pszAdminComp, szUrl, ARRAYSIZE(szUrl));
  4749. pszUrlList = szUrl;
  4750. while (pszUrl = StrTokEx(&pszUrlList, " ")) {
  4751. SHAnsiToUnicode(pszUrl, comp.wszSource, ARRAYSIZE(comp.wszSource));
  4752. dwDataLength = ARRAYSIZE(comp.wszSource);
  4753. ParseURLFromOutsideSourceW(comp.wszSource, comp.wszSource, &dwDataLength, NULL);
  4754. if (lstrcmp(aszAdminComp[i], REG_VAL_ADMINCOMP_ADD) == 0)
  4755. {
  4756. AddUrl(NULL, (LPCWSTR)comp.wszSource, &comp, ADDURL_SILENT);
  4757. fComponentsZoomDirty = TRUE;
  4758. }
  4759. else
  4760. {
  4761. RemoveDesktopItem((LPCOMPONENT)&comp, 0);
  4762. }
  4763. }
  4764. }
  4765. i++;
  4766. }
  4767. SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP, TEXT("LastSyncedTime"), REG_BINARY, (LPVOID)&ftAdminCompKey, sizeof(ftAdminCompKey));
  4768. }
  4769. // Go through the entire list of desktop components and ensure any split/fullscreen
  4770. // components are at their correct size/location.
  4771. if (fComponentsZoomDirty)
  4772. {
  4773. if (_hdsaComponent)
  4774. {
  4775. int i;
  4776. for (i = 0; i < DSA_GetItemCount(_hdsaComponent); i++)
  4777. {
  4778. COMPONENTA * pcompT;
  4779. if (pcompT = (COMPONENTA *)DSA_GetItemPtr(_hdsaComponent, i))
  4780. {
  4781. if (ISZOOMED(pcompT))
  4782. {
  4783. BOOL fAdjustListview = (pcompT->dwCurItemState & IS_ADJUSTLISTVIEW);
  4784. ZoomComponent(&pcompT->cpPos, pcompT->dwCurItemState, fAdjustListview);
  4785. if (fAdjustListview)
  4786. pcompT->dwCurItemState &= ~IS_ADJUSTLISTVIEW;
  4787. }
  4788. }
  4789. }
  4790. SetDesktopFlags(COMPONENTS_ZOOMDIRTY, 0);
  4791. }
  4792. }
  4793. // NOTE #1: The above initialization would have changed the Z-order because of
  4794. // SortAndRationalize and so we need to APPLY_SAVE here.
  4795. // Warning: APPLY_SAVE changes the dwID field of components. This should not
  4796. // be a problem because we do this just before generating a new HTML file.
  4797. // NOTE #2: Do NOT use AD_APPLY_FORCE here. That sets the _fPatternDirty too and
  4798. // that causes a SystemParametersInfo() call which results in WM_SYSCOLORCHANGE
  4799. // and this causes a refresh. So, we set the dirty bit explicitly here.
  4800. _fDirty = TRUE; // See Note#2 above.
  4801. ApplyChanges(AD_APPLY_SAVE | AD_APPLY_HTMLGEN);
  4802. lRet = ERROR_SUCCESS;
  4803. if (dwRestrictUpdate != dwRestrict)
  4804. SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_COMPONENTS_ROOT, REG_VAL_GENERAL_RESTRICTUPDATE, NULL, &dwRestrict, sizeof(dwRestrict));
  4805. }
  4806. if (hkey)
  4807. {
  4808. RegCloseKey(hkey);
  4809. }
  4810. return (lRet == ERROR_SUCCESS ? S_OK : E_FAIL);
  4811. }
  4812. //
  4813. // ReReadWallpaper()
  4814. // If the wallpaper was read when the active desktop was disabled, we would have read it from
  4815. // the old location. Now, if the active desktop is turned ON, then we need to re-read the wallpaper
  4816. // from the new location. We need to do this iff the wallpaper has not been changed in the mean-while
  4817. //
  4818. HRESULT CActiveDesktop::ReReadWallpaper(void)
  4819. {
  4820. if ((!_fDirty) || (!_co.fActiveDesktop)) //If nothing has changed OR if active desktop is OFF,
  4821. return(S_FALSE); // then nothing to do!
  4822. //ActiveDesktop is ON in our object. Read current shell state.
  4823. SHELLSTATE ss = {0};
  4824. SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE);
  4825. if (ss.fDesktopHTML)
  4826. return(S_FALSE); // Active Desktop state hasn't changed. So, nothing to do!
  4827. //So, Active desktop was originally OFF and now it is turned ON.
  4828. //If if someone changed the wallpaper, we should not mess with it.
  4829. if (_fWallpaperDirty || _fWallpaperChangedDuringInit)
  4830. return(S_FALSE);
  4831. // No one has changed the wallpaper. So, we must re-read it from the new wallpaper location
  4832. // sothat we get the correct wallpaper for the active desktop mode.
  4833. _ReadWallpaper(TRUE);
  4834. return(S_OK);
  4835. }
  4836. //
  4837. // GetADObjectFlags()
  4838. //
  4839. // Get the Active Desktop object's internal flags
  4840. //
  4841. HRESULT CActiveDesktop::GetADObjectFlags(LPDWORD lpdwFlags, DWORD dwMask)
  4842. {
  4843. ASSERT(lpdwFlags);
  4844. *lpdwFlags = 0; //Init the flags
  4845. if ((dwMask & GADOF_DIRTY) && _fDirty)
  4846. *lpdwFlags |= GADOF_DIRTY;
  4847. return(S_OK);
  4848. }
  4849. HRESULT ForceFullRefresh(void)
  4850. {
  4851. HWND hwndShell = GetShellWindow();
  4852. //Force a SHRefresh with this dummy call
  4853. SHGetSetSettings(NULL, 0, TRUE);
  4854. SendMessage(hwndShell, DTM_MAKEHTMLCHANGES, (WPARAM)0, (LPARAM)0L);
  4855. //Can't use dynamic html. We have to refresh the whole page.
  4856. SendMessage(hwndShell, WM_WININICHANGE, SPI_SETDESKWALLPAPER, (LPARAM)c_szRefreshDesktop);
  4857. return S_OK;
  4858. }
  4859. HRESULT CActiveDesktop::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog)
  4860. {
  4861. HRESULT hr = E_INVALIDARG;
  4862. if (pszPropName && pVar)
  4863. {
  4864. hr = E_FAIL;
  4865. if (StrCmpIW(pszPropName, c_wszPropName_IgnorePolicies) == 0)
  4866. {
  4867. pVar->vt = VT_BOOL;
  4868. pVar->boolVal = (_fIgnoreAddRemovePolicies ? VARIANT_TRUE : VARIANT_TRUE);
  4869. hr = S_OK;
  4870. }
  4871. else if (StrCmpIW(pszPropName, c_wszPropName_TSPerfBGPolicy) == 0)
  4872. {
  4873. BOOL fPolicySet = (IsTSPerfFlagEnabled(TSPerFlag_NoADWallpaper) || IsTSPerfFlagEnabled(TSPerFlag_NoWallpaper)); //No policy is set!
  4874. pVar->vt = VT_BOOL;
  4875. pVar->boolVal = (fPolicySet ? VARIANT_TRUE : VARIANT_TRUE);
  4876. hr = S_OK;
  4877. }
  4878. }
  4879. return hr;
  4880. }
  4881. HRESULT CActiveDesktop::Write(LPCOLESTR pszPropName, VARIANT *pVar)
  4882. {
  4883. HRESULT hr = E_INVALIDARG;
  4884. if (pszPropName && pVar)
  4885. {
  4886. hr = E_FAIL;
  4887. if ((StrCmpIW(pszPropName, c_wszPropName_IgnorePolicies) == 0) && (VT_BOOL == pVar->vt))
  4888. {
  4889. _fIgnoreAddRemovePolicies = (VARIANT_TRUE == pVar->boolVal);
  4890. hr = S_OK;
  4891. }
  4892. else if ((StrCmpIW(pszPropName, c_wszPropName_TSPerfBGPolicy) == 0) && (VT_BOOL == pVar->vt))
  4893. {
  4894. ForceFullRefresh();
  4895. hr = S_OK;
  4896. }
  4897. }
  4898. return hr;
  4899. }
  4900. /***
  4901. *char *StrTokEx(pstring, control) - tokenize string with delimiter in control
  4902. *
  4903. *Purpose:
  4904. * StrTokEx considers the string to consist of a sequence of zero or more
  4905. * text tokens separated by spans of one or more control chars. the first
  4906. * call, with string specified, returns a pointer to the first char of the
  4907. * first token, and will write a null char into pstring immediately
  4908. * following the returned token. when no tokens remain
  4909. * in pstring a NULL pointer is returned. remember the control chars with a
  4910. * bit map, one bit per ascii char. the null char is always a control char.
  4911. *
  4912. *Entry:
  4913. * char **pstring - ptr to ptr to string to tokenize
  4914. * char *control - string of characters to use as delimiters
  4915. *
  4916. *Exit:
  4917. * returns pointer to first token in string,
  4918. * returns NULL when no more tokens remain.
  4919. * pstring points to the beginning of the next token.
  4920. *
  4921. *WARNING!!!
  4922. * upon exit, the first delimiter in the input string will be replaced with '\0'
  4923. *
  4924. * copied from iert.lib
  4925. *******************************************************************************/
  4926. extern "C" char * __cdecl StrTokEx(char ** spstring, const char * scontrol)
  4927. {
  4928. unsigned char **pstring = (unsigned char**) spstring;
  4929. unsigned char *control = (unsigned char*) scontrol;
  4930. unsigned char *str;
  4931. const unsigned char *ctrl = control;
  4932. unsigned char map[32];
  4933. int count;
  4934. unsigned char *tokenstr;
  4935. if (*pstring == NULL)
  4936. return NULL;
  4937. /* Clear control map */
  4938. for (count = 0; count < 32; count++)
  4939. map[count] = 0;
  4940. /* Set bits in delimiter table */
  4941. do
  4942. {
  4943. map[*ctrl >> 3] |= (1 << (*ctrl & 7));
  4944. } while (*ctrl++);
  4945. /* Initialize str. */
  4946. str = *pstring;
  4947. /* Find beginning of token (skip over leading delimiters). Note that
  4948. * there is no token if this loop sets str to point to the terminal
  4949. * null (*str == '\0') */
  4950. while ( (map[*str >> 3] & (1 << (*str & 7))) && *str )
  4951. str++;
  4952. tokenstr = str;
  4953. /* Find the end of the token. If it is not the end of the string,
  4954. * put a null there. */
  4955. for ( ; *str ; str++ )
  4956. {
  4957. if ( map[*str >> 3] & (1 << (*str & 7)) )
  4958. {
  4959. *str++ = '\0';
  4960. break;
  4961. }
  4962. }
  4963. /* string now points to beginning of next token */
  4964. *pstring = str;
  4965. /* Determine if a token has been found. */
  4966. if ( tokenstr == str )
  4967. return NULL;
  4968. else
  4969. return (char*)tokenstr;
  4970. }