|
|
#include "stdafx.h"
#pragma hdrstop
#include "..\deskfldr.h"
#include "dutil.h"
extern "C" char * __cdecl StrTokEx(char ** pstring, const char * control);
#define DXA_GROWTH_CONST 10
#define ZINDEX_START 1000
#define MAXID_LENGTH 10 //Maximum number of digits in ID string plus 1.
#define TF_DESKSTAT 0
#define TF_DYNAMICHTML 0
IActiveDesktop *g_pActiveDesk = NULL;
#define c_szRegStrDesktop REGSTR_PATH_DESKTOP
#define c_szWallpaper REG_VAL_GENERAL_WALLPAPER
#define c_szBackupWallpaper REG_VAL_GENERAL_BACKUPWALLPAPER
#define c_szPattern TEXT("Pattern")
#define c_szTileWall REG_VAL_GENERAL_TILEWALLPAPER
#define c_szWallpaperStyle REG_VAL_GENERAL_WALLPAPERSTYLE
#define c_szWallpaperTime REG_VAL_GENERAL_WALLPAPERTIME
#define c_szWallpaperLocalTime REG_VAL_GENERAL_WALLPAPERLOCALTIME
#define c_szRefreshDesktop TEXT("RefreshDesktop")
#define c_szBufferedRefresh TEXT("BufferedRefresh")
#define COMP_TYPE 0x00000003
#define COMP_SELECTED 0x00002000
#define COMP_NOSCROLL 0x00004000
#ifdef DEBUG
#define ENTERPROC EnterProcDS
#define EXITPROC ExitProcDS
void EnterProcDS(DWORD dwTraceLevel, LPSTR szFmt, ...); void ExitProcDS(DWORD dwTraceLevel, LPSTR szFmt, ...);
extern DWORD g_dwDeskStatTrace;
#else
#ifndef CCOVER
#pragma warning(disable:4002)
#define ENTERPROC()
#define EXITPROC()
#else // ccover buildi
// these are needed because of a bug in cl.exe that results in improper processing
// of #pragma when run with cl -P, and then compiling
#define ENTERPROC 1 ? (void) 0 : (void)
#define EXITPROC 1 ? (void) 0 : (void)
#endif //end of ccover
#endif
MAKE_CONST_BSTR(s_sstrBeforeEnd, L"BeforeEnd"); MAKE_CONST_BSTR(s_sstrDeskMovr, L"DeskMovr"); MAKE_CONST_BSTR(s_sstrDeskMovrW, L"DeskMovrW"); MAKE_CONST_BSTR(s_sstrclassid, L"classid"); MAKE_CONST_BSTR(s_sstrEmpty, L"");
STDAPI ParseDesktopComponent(HWND hwndOwner, LPWSTR wszURL, COMPONENT *pInfo);
WCHAR wUnicodeBOM = 0xfeff; // Little endian unicode Byte Order Mark.First byte:0xff, Second byte: 0xfe.
//extern BOOL IsWallpaperDesktopV2(LPCTSTR lpszWallpaper);
CReadFileObj::CReadFileObj(LPCTSTR lpszFileName) { //Open the file
if ((_hFile = CreateFile(lpszFileName, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) { WCHAR wBOM; DWORD dwBytesRead = 0; if ((ReadFile(_hFile, (LPVOID)&wBOM, sizeof(WCHAR), &dwBytesRead, NULL)) && (dwBytesRead == sizeof(WCHAR))) { if (wBOM == wUnicodeBOM) _iCharset = UNICODE_HTML_CHARSET; else { //Note: Anything other than the little endian unicode file is treated as ansi.
_iCharset = ANSI_HTML_CHARSET; SetFilePointer(_hFile, 0L, NULL, FILE_BEGIN); //Seek to the begining of the file
} } } }
CReadFileObj::~CReadFileObj() { if (_hFile != INVALID_HANDLE_VALUE) { CloseHandle(_hFile); _hFile = NULL; } }
//
// This will read and if necessary convert between ANSI and UNICODE
//
HRESULT CReadFileObj::FileReadAndConvertChars(int iDestCharset, LPWSTR lpwszBuff, UINT uiCharsToRead, UINT *puiCharsActuallyRead, UINT *puiCharsConverted) { HRESULT hres = S_OK; DWORD dwCharsRead = 0; DWORD dwTotalCharsConverted = 0; if (_hFile != INVALID_HANDLE_VALUE) { if (_iCharset == UNICODE_HTML_CHARSET) { if (iDestCharset == UNICODE_HTML_CHARSET) { hres = FileReadCharsW(lpwszBuff, uiCharsToRead, (UINT *)&dwCharsRead); dwTotalCharsConverted = dwCharsRead; } else { //Destination is ansi; Read the UNICODE source and convert to ANSI.
WCHAR wszBuf[INTERNET_MAX_URL_LENGTH + 1]; //Temp buffer to read the UNICODE chars into.
LPSTR lpszBuff = (LPSTR)lpwszBuff;
DWORD dwTotalCharsToRead = (DWORD)uiCharsToRead; while(dwTotalCharsToRead) { DWORD dwCount; DWORD dwActuallyRead; // - 1 to give room for a null character at the end.
dwCount = (DWORD)min(dwTotalCharsToRead, (ARRAYSIZE(wszBuf) - 1)); if (ReadFile(_hFile, (LPSTR)wszBuf, dwCount*sizeof(WCHAR), &dwActuallyRead, NULL)) { DWORD dwConverted; dwActuallyRead = dwActuallyRead/sizeof(WCHAR); //Null terminate the source buffer.
wszBuf[dwActuallyRead] = L'\0'; //UNICODE null terminate the source.
//Convert what we just read.
dwConverted = SHUnicodeToAnsi(wszBuf, lpszBuff, dwActuallyRead+1); //+1 for null termination
//Update the count & stuff.
lpszBuff += dwConverted - 1; //Subtract the null.
dwTotalCharsToRead -= dwActuallyRead; dwCharsRead += dwActuallyRead; dwTotalCharsConverted += dwConverted - 1; //Subtract the null.
if (dwActuallyRead < dwCount) break; //We have reached the end of file.
} else { hres = E_FAIL; break; } } } } else { //Source file is ANSI. Check the Destination.
if (iDestCharset == ANSI_HTML_CHARSET) { //Destination is ANSI too! Cool! No need for conversion!
hres = FileReadCharsA((LPSTR)lpwszBuff, uiCharsToRead, (UINT *)&dwCharsRead); dwTotalCharsConverted = dwCharsRead; } else { //Destination is UNICODE! Read the ansi and convert it to UNICODE!
char szBuf[INTERNET_MAX_URL_LENGTH + 1]; //Temp buffer to read the ansi chars into.
DWORD dwTotalCharsToRead = (DWORD)uiCharsToRead;
while(dwTotalCharsToRead) { DWORD dwCount; DWORD dwActuallyRead;
// - 1 to give room for a null character at the end.
dwCount = (DWORD)min(dwTotalCharsToRead, (ARRAYSIZE(szBuf) - 1));
if (ReadFile(_hFile, (LPSTR)szBuf, dwCount, &dwActuallyRead, NULL)) { DWORD dwConverted; //Null terminate the source buffer.
szBuf[dwActuallyRead] = '\0'; //ANSI null terminate the source.
//Convert what we just read.
dwConverted = SHAnsiToUnicode(szBuf, lpwszBuff, dwActuallyRead+1); //+1 for null termination
//Update the count & stuff.
lpwszBuff += dwConverted - 1; //Subtract the null.
dwTotalCharsToRead -= dwActuallyRead; dwCharsRead += dwActuallyRead; dwTotalCharsConverted += dwConverted - 1; //Subtract the null.
if (dwActuallyRead < dwCount) break; //We have reached the end of file.
} else { hres = E_FAIL; break; } } //while
} } } else hres = E_FAIL; //The file handle is bad.
*puiCharsActuallyRead = (UINT)dwCharsRead; *puiCharsConverted = (UINT)dwTotalCharsConverted; return hres; }
HRESULT CReadFileObj::FileReadCharsA(LPSTR lpszBuff, UINT uiCharsToRead, UINT *puiCharsActuallyRead) { HRESULT hres = E_FAIL; DWORD dwCharsRead = 0; if ((_hFile != INVALID_HANDLE_VALUE) && (_iCharset == ANSI_HTML_CHARSET) && ReadFile(_hFile, (LPVOID)lpszBuff, (DWORD)(uiCharsToRead), &dwCharsRead, NULL)) { dwCharsRead = dwCharsRead; //get the number of wchars read.
hres = S_OK; } *puiCharsActuallyRead = (UINT)dwCharsRead; return hres; }
//
// NOTE: The uiCharsToRead must be atleast one less than the size of the buffer (lpwszBuff)
// because one null may be written at the end of the buffer by SHAnsiToUnicode().
//
HRESULT CReadFileObj::FileReadCharsW(LPWSTR lpwszBuff, UINT uiCharsToRead, UINT *puiCharsActuallyRead) { HRESULT hres = E_FAIL; DWORD dwCharsRead = 0; if ((_hFile != INVALID_HANDLE_VALUE) && (_iCharset == UNICODE_HTML_CHARSET) && ReadFile(_hFile, (LPVOID)lpwszBuff, (DWORD)(uiCharsToRead*sizeof(WCHAR)), &dwCharsRead, NULL)) { dwCharsRead = dwCharsRead/sizeof(WCHAR); //get the number of wchars read.
hres = S_OK; } *puiCharsActuallyRead = (UINT)dwCharsRead; return hres; }
HRESULT CReadFileObj::FileSeekChars(LONG lCharOffset, DWORD dwOrigin) { HRESULT hres = E_FAIL;
if (_hFile != INVALID_HANDLE_VALUE) { if (SetFilePointer(_hFile, lCharOffset*((_iCharset == UNICODE_HTML_CHARSET) ? sizeof(WCHAR) : sizeof(char)), NULL, dwOrigin) != INVALID_SET_FILE_POINTER) hres = S_OK; }
return hres; }
HRESULT CReadFileObj::FileGetCurCharOffset(LONG *plCharOffset) { HRESULT hres = E_FAIL; DWORD dwByteOffset = 0;
*plCharOffset = 0; if (_hFile != INVALID_HANDLE_VALUE) { if ((dwByteOffset = SetFilePointer(_hFile, 0L, NULL, FILE_CURRENT)) != INVALID_SET_FILE_POINTER) { *plCharOffset = dwByteOffset/((_iCharset == UNICODE_HTML_CHARSET) ? sizeof(WCHAR) : sizeof(char)); hres = S_OK; } }
return hres; }
BOOL GetStringFromReg(HKEY hkey, LPCTSTR lpszSubkey, LPCTSTR lpszValueName, LPTSTR lpszValue, DWORD cchSizeofValueBuff) { DWORD cb = cchSizeofValueBuff * sizeof(lpszValue[0]); return (ERROR_SUCCESS == SHGetValue(hkey, lpszSubkey, lpszValueName, NULL, lpszValue, &cb)); }
void GetWallpaperFileTime(LPCTSTR pszWallpaper, LPFILETIME lpftFileTime) { HANDLE hFile; BOOL fRet = FALSE;
if ((hFile = CreateFile(pszWallpaper, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0)) != INVALID_HANDLE_VALUE) { fRet = GetFileTime(hFile, NULL, NULL, lpftFileTime);
CloseHandle(hFile); }
if (!fRet) { ZeroMemory(lpftFileTime, sizeof(FILETIME)); }
// no return value
}
BOOL HasWallpaperReallyChanged(LPCTSTR pszRegKey, LPTSTR pszOldWallpaper, LPTSTR pszBackupWallpaper, DWORD dwOldWallpaperStyle, DWORD dwNewWallpaperStyle) { // we default to TRUE here.
if ((dwOldWallpaperStyle == dwNewWallpaperStyle) && (0 == lstrcmpi(pszOldWallpaper, pszBackupWallpaper))) { // The wallpaper filename and style hasn't changed.
// But, the content of this file could have changed.
// See if the content has changed by looking at the
// last-written date and time stamp on this file.
FILETIME ftOld, ftBack; DWORD cbBack = sizeof(ftBack);
// if either of these fail, then they will
// remain Zero so the compare will
// be successful.
GetWallpaperFileTime(pszOldWallpaper, &ftOld); if (ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperTime, NULL, &ftBack, &cbBack)) { ZeroMemory(&ftBack, sizeof(ftBack)); }
//Get the last written time of the backup wallpaper from registry
if (0 == CompareFileTime(&ftOld, &ftBack)) return FALSE; // everything is the same!
// Win2K QFE bug 10689 (AndrewGr)
// same check, but instead of checking UTC time, check local time converted to UTC time
// this is because FAT disks store local time, not UTC time
FILETIME ftLocalBack, ftLocalBackUtc;
cbBack = sizeof(ftLocalBack);
if (ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperLocalTime, NULL, &ftLocalBack, &cbBack)) { ZeroMemory(&ftLocalBack, sizeof(ftLocalBack)); }
LocalFileTimeToFileTime(&ftLocalBack, &ftLocalBackUtc); if (ftOld.dwLowDateTime == ftLocalBackUtc.dwLowDateTime && (ftOld.dwHighDateTime == ftLocalBackUtc.dwHighDateTime)) // everything is the same!
return FALSE;
} return TRUE; }
//-------------------------------------------------------------------------------------------------------------//
// Function: ReadWallpaperStyleFromReg()
//
// This function reads the "TileWallpaper" and the "WallpaperStyle" from the given location
// in the registry.
//
//-------------------------------------------------------------------------------------------------------------//
int GetIntFromReg(HKEY hKey, LPCTSTR lpszSubkey, LPCTSTR lpszNameValue, int iDefault) { TCHAR szValue[20]; DWORD dwSizeofValueBuff = sizeof(szValue); int iRetValue = iDefault; DWORD dwType;
if ((SHGetValue(hKey, lpszSubkey, lpszNameValue, &dwType, szValue, &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff) { if (dwType == REG_SZ) { iRetValue = (int)StrToInt(szValue); } }
return iRetValue; }
void ReadWallpaperStyleFromReg(LPCTSTR pszRegKey, DWORD *pdwWallpaperStyle, BOOL fIgnorePlatforms) { if (GetIntFromReg(HKEY_CURRENT_USER, pszRegKey, c_szTileWall, WPSTYLE_TILE)) { // "Tile" overrides the "Stretch" style.
*pdwWallpaperStyle = WPSTYLE_TILE; } else { // else, STRETCH or CENTER.
*pdwWallpaperStyle = GetIntFromReg(HKEY_CURRENT_USER, pszRegKey, c_szWallpaperStyle, WPSTYLE_CENTER); } }
BOOL CActiveDesktop::_IsDisplayInSafeMode(void) { WCHAR wszDisplay[MAX_PATH]; DWORD dwcch = MAX_PATH;
return (SUCCEEDED(GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY)) && (0 == StrCmpW(wszDisplay, REG_DESKCOMP_SAFEMODE_SUFFIX_L))); }
BOOL ReadPolicyForWallpaper(LPTSTR pszPolicy, DWORD cchPolicy) { BOOL fPolicySet = FALSE; DWORD cb = cchPolicy * sizeof(pszPolicy[0]); if ((SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_WP_POLICY, c_szWallpaper, NULL, pszPolicy, &cb) == ERROR_SUCCESS) && cb) { // even if this value was originally REG_SZ it may still
// have environment vars in it for legacy reasons!
if (SUCCEEDED(PathExpandEnvStringsWrap(pszPolicy, cchPolicy))) { fPolicySet = TRUE; //Policy is there!
} else { pszPolicy[0] = 0; // if we couldn't expand correctly, null it out to be safe
} } else { // See if the TS Perf policy is set to turn it off for perf.
fPolicySet = (IsTSPerfFlagEnabled(TSPerFlag_NoADWallpaper) || IsTSPerfFlagEnabled(TSPerFlag_NoWallpaper)); //No policy is set!
}
return fPolicySet; }
HRESULT GetWallpaperPath(HKEY hKey, LPCTSTR pszKey, LPCTSTR pszValue, LPCTSTR pszFallback, LPTSTR pszPath, DWORD cchSize) { HRESULT hr;
if (GetStringFromReg(hKey, pszKey, pszValue, pszPath, cchSize)) { hr = PathExpandEnvStringsWrap(pszPath, cchSize); } else if (pszFallback) { hr = StringCchCopy(pszPath, cchSize, pszFallback); } else { pszPath[0] = 0; hr = S_FALSE; // couldn't get it from registry, we null the output buffer, but this is not catastrophic
}
return hr; }
BOOL ReadPolicyForWPStyle(LPDWORD lpdwStyle) { DWORD dwStyle; DWORD dwType; TCHAR szValue[20]; DWORD dwSizeofValueBuff = sizeof(szValue); BOOL fRet = FALSE;
// The caller can passin a NULL, if they are not interested in the actual value and they just
// want to know if this policy is set or not.
if (!lpdwStyle) lpdwStyle = &dwStyle;
if ((SHGetValue(HKEY_CURRENT_USER, REGSTR_PATH_WP_POLICY, c_szWallpaperStyle, &dwType, szValue, &dwSizeofValueBuff) == ERROR_SUCCESS) && dwSizeofValueBuff) { if (dwType == REG_SZ) { *lpdwStyle = (DWORD)StrToInt(szValue); fRet = TRUE; } }
return fRet; }
BOOL CActiveDesktop::_ReadWallpaper(BOOL fActiveDesktop) { ENTERPROC(2, "DS ReadWallpaper()");
TCHAR szDeskcomp[MAX_PATH]; GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, _pszScheme);
_fPolicyForWPName = ReadPolicyForWallpaper(_szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper)); _fPolicyForWPStyle = ReadPolicyForWPStyle(&_wpo.dwStyle); //
// Read in the wallpaper and style from the appropriate registry location.
//
LPCTSTR pszRegKey; if (fActiveDesktop) { pszRegKey = szDeskcomp; TCHAR szOldWallpaper[MAX_PATH]; DWORD dwOldWallpaperStyle;
// Read the Wallpaper from the Old location.
if (S_OK != GetWallpaperPath(HKEY_CURRENT_USER, c_szRegStrDesktop, c_szWallpaper, NULL, szOldWallpaper, ARRAYSIZE(szOldWallpaper))) { return FALSE; }
// Read wallpaper style from the old location.
ReadWallpaperStyleFromReg((LPCTSTR)c_szRegStrDesktop, &dwOldWallpaperStyle, FALSE);
// Read the wallpaper from the new location too!
if ((!_fPolicyForWPName) || (_IsDisplayInSafeMode())) { HRESULT hrPath = GetWallpaperPath(HKEY_CURRENT_USER, pszRegKey, c_szWallpaper, szOldWallpaper, _szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper)); if (S_FALSE == hrPath) { pszRegKey = c_szRegStrDesktop; } else if (FAILED(hrPath)) { return FALSE; } }
//Read wallpaper style from the new location too!
if (!_fPolicyForWPStyle) { ReadWallpaperStyleFromReg(pszRegKey, &_wpo.dwStyle, FALSE); } //If there is a Safe mode scheme here do NOT attempt to change wallpaper
if ((!_IsDisplayInSafeMode()) && (!_fPolicyForWPName)) { //Read what is stored as "Backup" wallpaper.
if (S_OK != GetWallpaperPath(HKEY_CURRENT_USER, pszRegKey, c_szBackupWallpaper, szOldWallpaper, _szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper))) { return FALSE; } else { //See if the Old wallpaper is differnet from the backed up wallpaper
if (HasWallpaperReallyChanged(pszRegKey, szOldWallpaper, _szBackupWallpaper, dwOldWallpaperStyle, _wpo.dwStyle)) { //They are different. This means that some other app has changed the "Old" wallpaper
//after the last time we backed it up in the registry.
// Make this wallpaper as the Selected wallpaper!
if (FAILED(StringCchCopy(_szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper), szOldWallpaper))) { return FALSE; } else { _wpo.dwStyle = dwOldWallpaperStyle;
_fWallpaperDirty = TRUE; _fWallpaperChangedDuringInit = TRUE; } } }
} //Make a backup of the "Old" wallpaper from szOldWallpaper
if (FAILED(StringCchCopy(_szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper), szOldWallpaper))) { _szBackupWallpaper[0] = 0; // on failure null it out, this value is just an optimization
} } else { pszRegKey = c_szRegStrDesktop; //Get it from the old location!
//Since active desktop is not available, read wallpaper from old location.
if (!_fPolicyForWPName) { if (S_OK != GetWallpaperPath(HKEY_CURRENT_USER, pszRegKey, c_szWallpaper, NULL, _szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper))) { return FALSE; } }
//Read the wallpaper style
if (!_fPolicyForWPStyle) ReadWallpaperStyleFromReg(pszRegKey, &_wpo.dwStyle, TRUE);
//Make a backup of the "Old" wallpaper from _szSelectedWallpaper
if (FAILED(StringCchCopy(_szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper), _szSelectedWallpaper))) { _szBackupWallpaper[0] = 0; // on failure null it out, this value is just an optimization
} }
EXITPROC(2, "DS ReadWallpaper! (_szSelectedWP=>%s<)", _szSelectedWallpaper);
return TRUE; }
void CActiveDesktop::_ReadPattern(void) { ENTERPROC(2, "DS ReadPattern()");
GetStringFromReg(HKEY_CURRENT_USER, c_szRegStrDesktop, c_szPattern, _szSelectedPattern, ARRAYSIZE(_szSelectedPattern));
EXITPROC(2, "DS ReadPattern! (_szSelectedPattern=>%s<)", _szSelectedPattern); }
void CActiveDesktop::_ReadComponent(HKEY hkey, LPCTSTR pszComp) { ENTERPROC(2, "DS ReadComponent(hk=%08X,pszComp=>%s<)", hkey, pszComp);
HKEY hkeyComp;
if (RegOpenKeyEx(hkey, pszComp, 0, KEY_READ, &hkeyComp) == ERROR_SUCCESS) { DWORD cbSize; COMPONENTA comp; comp.dwSize = sizeof(COMPONENTA);
//
// Read in the source string.
//
cbSize = sizeof(comp.szSource); if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_SOURCE, NULL, NULL, (LPBYTE)&comp.szSource, &cbSize) != ERROR_SUCCESS) { comp.szSource[0] = TEXT('\0'); }
//
// Read in the SubscribedURL string.
//
cbSize = sizeof(comp.szSubscribedURL); if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_SUBSCRIBED_URL, NULL, NULL, (LPBYTE)&comp.szSubscribedURL, &cbSize) != ERROR_SUCCESS) { comp.szSubscribedURL[0] = TEXT('\0'); }
//
// Read in the Friendly name string.
//
cbSize = sizeof(comp.szFriendlyName); if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_NAME, NULL, NULL, (LPBYTE)&comp.szFriendlyName, &cbSize) != ERROR_SUCCESS) { comp.szFriendlyName[0] = TEXT('\0'); }
//
// Read in and parse the flags.
//
DWORD dwFlags; cbSize = sizeof(dwFlags); if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_FLAGS, NULL, NULL, (LPBYTE)&dwFlags, &cbSize) != ERROR_SUCCESS) { dwFlags = 0; } comp.iComponentType = dwFlags & COMP_TYPE; comp.fChecked = (dwFlags & COMP_SELECTED) != 0; comp.fNoScroll = (dwFlags & COMP_NOSCROLL) != 0; comp.fDirty = FALSE; //Reading it fresh from registry; Can't be dirty!
//
// Read in the location.
//
cbSize = sizeof(comp.cpPos); if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_POSITION, NULL, NULL, (LPBYTE)&comp.cpPos, &cbSize) != ERROR_SUCCESS) { ZeroMemory(&comp.cpPos, sizeof(comp.cpPos)); }
//
// In IE4.x, we have a very huge positive number (0x7fffffff) as the COMPONENT_TOP;
// As a result some component's z-index overflowed into the negative range (0x80000003)
// To fix this, we halved the COMPONENT_TOP (0x3fffffff) and also check for negative z-index
// values and covert them to postive values.
if (comp.cpPos.izIndex < 0) comp.cpPos.izIndex = COMPONENT_TOP;
//
// Make sure the cpPos.dwSize is set to correct value
//
comp.cpPos.dwSize = sizeof(COMPPOS);
//
// Read in the current ItemState
//
cbSize = sizeof(comp.dwCurItemState); if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_CURSTATE, NULL, NULL, (LPBYTE)&comp.dwCurItemState, &cbSize) != ERROR_SUCCESS) { //If the item state is missing, we must be reading from IE4 machine.
comp.dwCurItemState = IS_NORMAL; }
//
// Read in the Original state info.
//
cbSize = sizeof(comp.csiOriginal); if ((SHQueryValueEx(hkeyComp, REG_VAL_COMP_ORIGINALSTATEINFO, NULL, NULL, (LPBYTE)&comp.csiOriginal, &cbSize) != ERROR_SUCCESS) || (comp.csiOriginal.dwSize != sizeof(comp.csiOriginal))) { //If the item state is missing, we must be reading from IE4 machine.
// Set the OriginalState to the default info.
SetStateInfo(&comp.csiOriginal, &comp.cpPos, IS_NORMAL); comp.csiOriginal.dwHeight = comp.csiOriginal.dwWidth = COMPONENT_DEFAULT_WIDTH; }
//
// Read in the Restored state info.
//
cbSize = sizeof(comp.csiRestored); if (SHQueryValueEx(hkeyComp, REG_VAL_COMP_RESTOREDSTATEINFO, NULL, NULL, (LPBYTE)&comp.csiRestored, &cbSize) != ERROR_SUCCESS) { //If the item state is missing, we must be reading from IE4 machine.
// Set the restored State to the default info.
SetStateInfo(&comp.csiRestored, &comp.cpPos, IS_NORMAL); }
//
// Add the component to the component list.
//
AddComponentPrivate(&comp, StrToInt(pszComp));
//
// Increment our counter so we know where to add any new
// components after we're done.
//
_dwNextID++;
RegCloseKey(hkeyComp); }
EXITPROC(2, "DS ReadComponent!"); }
typedef struct _tagSortStruct { int ihdsaIndex; int izIndex; } SORTSTRUCT;
int CALLBACK pfnComponentSort(LPVOID p1, LPVOID p2, LPARAM lParam) { SORTSTRUCT * pss1 = (SORTSTRUCT *)p1; SORTSTRUCT * pss2 = (SORTSTRUCT *)p2;
if (pss1->izIndex > pss2->izIndex) return 1;
if (pss1->izIndex < pss2->izIndex) return -1;
return(0); }
//
// ModifyZIndex
//
// Little helper function to put the zindex of the windowed and windowless components
// into correct buckets so that zorting will produce a correct order by zindex.
//
// If we don't do this then windowless components may end up zordering above windowed ones.
//
void ModifyZIndex(COMPONENTA * pcomp) { if (pcomp->cpPos.izIndex != COMPONENT_TOP) { if (!IsWindowLessComponent(pcomp)) pcomp->cpPos.izIndex += COMPONENT_TOP_WINDOWLESS; } else { if (IsWindowLessComponent(pcomp)) pcomp->cpPos.izIndex = COMPONENT_TOP_WINDOWLESS; } }
//
// SortAndRationalize
//
// SortAndRationalize will take an unsorted component list and sort it such that the components
// come out in the correct z-index indicated order. It will also rebase the z-index values at
// a known constant so that the z-index values will not grow endlessly. SortAndRationalize also
// imposes windowed vs. windowless criteria to the zindex values such that windowless components
// always zorder under windowed ones.
//
void CActiveDesktop::_SortAndRationalize(void) { int icComponents; HDPA hdpa;
if (_hdsaComponent && ((icComponents = DSA_GetItemCount(_hdsaComponent)) > 1) && (hdpa = DPA_Create(0))) { COMPONENTA * pcomp; SORTSTRUCT * pss; int i, iCur = ZINDEX_START; BOOL fInsertFailed = FALSE; HDSA hdsaOld;
// Go through each component and insert it's hdsa-index and zindex into the hdpa
for (i = 0; i < icComponents; i++) { if (!(pss = (SORTSTRUCT *)LocalAlloc(LPTR, sizeof(SORTSTRUCT)))) break;
pcomp = (COMPONENTA *)DSA_GetItemPtr(_hdsaComponent, i); ModifyZIndex(pcomp); pss->ihdsaIndex = i; pss->izIndex = pcomp->cpPos.izIndex; if (DPA_AppendPtr(hdpa, (void FAR *)pss) == -1) { LocalFree((HANDLE)pss); break; } }
// Sort the hdpa by zindex
DPA_Sort(hdpa, pfnComponentSort, 0);
// Save old values
hdsaOld = _hdsaComponent;
// Null out the old hdsa, so AddComponentPrivate will create a new one
_hdsaComponent = NULL;
// Now go through the sorted hdpa and update the component zindex with a ZINDEX_START based zindex, then
// add the component to the new hdsa in sorted order.
for (i = 0; i < icComponents; i++) { if (!(pss = (SORTSTRUCT *)DPA_GetPtr(hdpa, i))) break; // Get component and update it's zIndex and id
pcomp = (COMPONENTA *)DSA_GetItemPtr(hdsaOld, pss->ihdsaIndex); pcomp->cpPos.izIndex = iCur; iCur += 2;
// Free ptr
LocalFree((HANDLE)pss);
// Add to new hdsa in sorted order
if (!fInsertFailed) { fInsertFailed = !AddComponentPrivate(pcomp, pcomp->dwID); } }
// If we're completely successfull then destroy the old hdsa. Otherwise we need
// to destroy the new one and restore the old one.
if ((i == icComponents) && !fInsertFailed) { DSA_Destroy(hdsaOld); } else { if (_hdsaComponent) DSA_Destroy(_hdsaComponent); _hdsaComponent = hdsaOld; }
DPA_Destroy(hdpa); } }
void CActiveDesktop::_ReadComponents(BOOL fActiveDesktop) { ENTERPROC(2, "DS ReadComponents()");
HKEY hkey; TCHAR szDeskcomp[MAX_PATH];
GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_COMPONENTS, _pszScheme); if (RegOpenKeyEx(HKEY_CURRENT_USER, szDeskcomp, 0, KEY_READ, &hkey) == ERROR_SUCCESS) { DWORD cbSize; int i = 0; TCHAR lpszSubkey[MAX_PATH];
//
// Read in the general settings.
//
DWORD dwSettings; cbSize = sizeof(dwSettings); if (SHQueryValueEx(hkey, REG_VAL_COMP_SETTINGS, NULL, NULL, (LPBYTE)&dwSettings, &cbSize) == ERROR_SUCCESS) { _co.fEnableComponents = (dwSettings & COMPSETTING_ENABLE) != 0; } _co.fActiveDesktop = fActiveDesktop;
//
// Read in all the desktop components
//
while (RegEnumKey(hkey, i, lpszSubkey, ARRAYSIZE(lpszSubkey)) == ERROR_SUCCESS) { _ReadComponent(hkey, lpszSubkey); i++; }
_SortAndRationalize();
RegCloseKey(hkey); }
EXITPROC(2, "DS ReadComponents!"); }
void CActiveDesktop::_Initialize(void) { ENTERPROC(2, "DS Initialize()");
if (!_fInitialized) { _fInitialized = TRUE; InitDeskHtmlGlobals();
SHELLSTATE ss = {0}; SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); BOOL fActiveDesktop = BOOLIFY(ss.fDesktopHTML); _co.dwSize = sizeof(_co); _wpo.dwSize = sizeof(_wpo);
//
// This per-user registry branch may not exist for this user. Or, even if
// it does exist, it may have some stale info. So ensure that atlreast the
// default components are there and that the html version is current for this
// branch of the registry!
// If everything is current, the following function does nothing!
//
CDeskHtmlProp_RegUnReg(TRUE); //TRUE => install.
_ReadWallpaper(fActiveDesktop); _ReadPattern(); _ReadComponents(fActiveDesktop);
// If we are in safemode, the we can not use Dynamic Html to make updates because
// updates involve complete change of background Html.
if (_IsDisplayInSafeMode()) _fUseDynamicHtml = FALSE; else _fUseDynamicHtml = TRUE; //Any component added after the initialization must go through dynamic html.
_fDirty = FALSE; _fNeedBodyEnd = FALSE; }
EXITPROC(2, "DS Initialize!"); }
void CActiveDesktop::_SaveWallpaper(void) { ENTERPROC(2, "DS SaveWallpaper"); TCHAR szDeskcomp[MAX_PATH]; BOOL fNormalWallpaper;
GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, _pszScheme);
//
// Compute tiling string.
//
TCHAR szTiled[2]; szTiled[0] = TEXT('0') + (TCHAR)(_wpo.dwStyle & WPSTYLE_TILE); szTiled[1] = NULL;
//
// Compute the Wallpaper styling string
//
TCHAR szWPStyle[2]; //
// NOTE: If WPSTYLE_TILE is set, we still want to say WallpaperStyle="0"; This won't hurt
// because TileWallpaper="1" will over-ride this anyway.
// The reason for this hack is that during memphis setup, they put a tiled wallpaper. Then we
// write WallpaperStyle=1 and TileWallpaper=1 in new and old locations. Then, then change
// the wallpaper and set TileWallpaper=0. Since the WallpaperStyle continues to be 1, they
// get a tiled wallpaper finally. The following is to avoid this problem!
//
szWPStyle[0] = TEXT('0') + (TCHAR)(_wpo.dwStyle & WPSTYLE_STRETCH); szWPStyle[1] = NULL;
//
// Write out wallpaper settings in new active desktop area.
//
if (_fWallpaperDirty || _fWallpaperChangedDuringInit) { if (!_fPolicyForWPStyle) { SHSetValue(HKEY_CURRENT_USER, szDeskcomp, c_szTileWall, REG_SZ, szTiled, CbFromCch(lstrlen(szTiled)+1)); }
//
// Note: We do not write the Wallpaper Style string for older systems because we do not
// want to over-write what PlusPack writes. However, for newer Operating systems, we
// want to write the WallpaperStyle also.
//
if (!_fPolicyForWPStyle) { SHSetValue(HKEY_CURRENT_USER, szDeskcomp, c_szWallpaperStyle, REG_SZ, szWPStyle, CbFromCch(lstrlen(szWPStyle)+1)); }
if (!_fPolicyForWPName) { SHRegSetPath(HKEY_CURRENT_USER, szDeskcomp, c_szWallpaper, _szSelectedWallpaper, 0); } }
if (fNormalWallpaper = IsNormalWallpaper(_szSelectedWallpaper)) { if (FAILED(StringCchCopy(_szBackupWallpaper, ARRAYSIZE(_szBackupWallpaper), _szSelectedWallpaper))) { _szBackupWallpaper[0] = 0; } }
if (!_fPolicyForWPName) { FILETIME ft, ftLocal; GetWallpaperFileTime(_szBackupWallpaper, &ft); FileTimeToLocalFileTime(&ft, &ftLocal); // for FAT systems to track across DST changes
// Backup the "Old type" wallpaper's name here in the new location
// sothat we can detect when this gets changed by some other app.
SHRegSetPath(HKEY_CURRENT_USER, szDeskcomp, c_szBackupWallpaper, _szBackupWallpaper, 0);
SHSetValue(HKEY_CURRENT_USER, szDeskcomp, c_szWallpaperTime, REG_BINARY, &ft, sizeof(ft));
SHSetValue(HKEY_CURRENT_USER, szDeskcomp, c_szWallpaperLocalTime, REG_BINARY, &ftLocal, sizeof(ftLocal)); // AndrewGr save local time not UTC time
} //
// Even if this wallpaper is not valid in normal desktop (i.e., even if it is not a .BMP),
// write it out in normal desktop registry area.
//
if (_fWallpaperDirty) { if (!_fPolicyForWPStyle) { SHSetValue(HKEY_CURRENT_USER, c_szRegStrDesktop, c_szTileWall, REG_SZ, szTiled, CbFromCch(lstrlen(szTiled)+1)); } //
// Note: We do not write the Wallpaper Style string for older systems because we do not
// want to over-write what PlusPack writes. However, for newer Operating systems, we
// want to write the WallpaperStyle also.
//
if (!_fPolicyForWPStyle) { SHSetValue(HKEY_CURRENT_USER, c_szRegStrDesktop, c_szWallpaperStyle, REG_SZ, szWPStyle, CbFromCch(lstrlen(szWPStyle)+1)); }
if (!_fPolicyForWPName) { SystemParametersInfo(SPI_SETDESKWALLPAPER, 0, (fNormalWallpaper ? _szSelectedWallpaper : _szBackupWallpaper), SPIF_UPDATEINIFILE); } }
EXITPROC(2, "DS SaveWallpaper"); }
void CActiveDesktop::_SaveComponent(HKEY hkey, int iIndex, COMPONENTA *pcomp) { ENTERPROC(2, "DS SaveComponent(hkey=%08X,iIndex=%d,pcomp=%08X)", hkey, iIndex, pcomp);
TCHAR szSubKey[8]; HKEY hkeySub;
if (SUCCEEDED(StringCchPrintf(szSubKey, ARRAYSIZE(szSubKey), TEXT("%d"), iIndex))) { if (ERROR_SUCCESS == RegCreateKeyEx(hkey, szSubKey, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkeySub, 0)) { pcomp->fDirty = FALSE; //Since we are saving in the registry, reset this!
//
// Write out the source string and Friendly name string.
//
RegSetValueEx(hkeySub, REG_VAL_COMP_SOURCE, 0, REG_SZ, (LPBYTE)pcomp->szSource, (lstrlen(pcomp->szSource)+1)*sizeof(TCHAR)); RegSetValueEx(hkeySub, REG_VAL_COMP_SUBSCRIBED_URL, 0, REG_SZ, (LPBYTE)pcomp->szSubscribedURL, (lstrlen(pcomp->szSubscribedURL)+1)*sizeof(TCHAR)); RegSetValueEx(hkeySub, REG_VAL_COMP_NAME, 0, REG_SZ, (LPBYTE)pcomp->szFriendlyName, (lstrlen(pcomp->szFriendlyName)+1)*sizeof(TCHAR));
//
// Compute and write out flags.
//
DWORD dwFlags = 0; dwFlags |= pcomp->iComponentType; if (pcomp->fChecked) { dwFlags |= COMP_SELECTED; } if (pcomp->fNoScroll) { dwFlags |= COMP_NOSCROLL; } RegSetValueEx(hkeySub, REG_VAL_COMP_FLAGS, 0, REG_DWORD, (LPBYTE)&dwFlags, sizeof(dwFlags));
//
// Write out the position.
//
RegSetValueEx(hkeySub, REG_VAL_COMP_POSITION, 0, REG_BINARY, (LPBYTE)&pcomp->cpPos, sizeof(pcomp->cpPos));
// Write out the Current state
RegSetValueEx(hkeySub, REG_VAL_COMP_CURSTATE, 0, REG_DWORD, (LPBYTE)&pcomp->dwCurItemState, sizeof(pcomp->dwCurItemState));
// Write out the Original State Info
RegSetValueEx(hkeySub, REG_VAL_COMP_ORIGINALSTATEINFO, 0, REG_BINARY, (LPBYTE)&pcomp->csiOriginal, sizeof(pcomp->csiOriginal)); // Write out the Restored State Info
RegSetValueEx(hkeySub, REG_VAL_COMP_RESTOREDSTATEINFO, 0, REG_BINARY, (LPBYTE)&pcomp->csiRestored, sizeof(pcomp->csiRestored));
RegCloseKey(hkeySub); } } EXITPROC(2, "DS SaveComponent!"); }
void CActiveDesktop::_SaveComponents(void) { ENTERPROC(2, "DS SaveComponents"); DWORD dwFlags = 0, dwDataLength = sizeof(dwFlags); int i; TCHAR szDeskcomp[MAX_PATH];
GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_COMPONENTS, _pszScheme);
//
// We need to preserve the old GENFLAGS, so read them now before we roach them.
//
SHGetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_COMP_GENFLAGS, NULL, &dwFlags, &dwDataLength);
//
// Delete the entire registry key.
//
SHDeleteKey(HKEY_CURRENT_USER, szDeskcomp);
//
// Recreate the registry key.
//
HKEY hkey; if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_CURRENT_USER, szDeskcomp, 0, NULL, 0, KEY_SET_VALUE, NULL, &hkey, 0)) { //
// Write out the version number.
//
DWORD dw = CUR_DESKHTML_VERSION; RegSetValueEx(hkey, REG_VAL_COMP_VERSION, 0, REG_DWORD, (LPBYTE)(&dw), sizeof(dw));
dw = CUR_DESKHTML_MINOR_VERSION; RegSetValueEx(hkey, REG_VAL_COMP_MINOR_VERSION, 0, REG_DWORD, (LPBYTE)(&dw), sizeof(dw));
//
// Write out the general settings.
//
DWORD dwSettings = 0; if (_co.fEnableComponents) { dwSettings |= COMPSETTING_ENABLE; } RegSetValueEx(hkey, REG_VAL_COMP_SETTINGS, 0, REG_DWORD, (LPBYTE)&dwSettings, sizeof(dwSettings));
//
// Write out the general flags
//
RegSetValueEx(hkey, REG_VAL_COMP_GENFLAGS, 0, REG_DWORD, (LPBYTE)&dwFlags, sizeof(dwFlags));
if (_hdsaComponent) { //
// Write out the settings for each component
//
for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++) { COMPONENTA * pcomp;
if (pcomp = (COMPONENTA *)DSA_GetItemPtr(_hdsaComponent, i)) { pcomp->dwID = i; _SaveComponent(hkey, i, pcomp); } } }
RegCloseKey(hkey); }
EXITPROC(2, "DS SaveComponents"); }
void CActiveDesktop::_SavePattern(DWORD dwFlags) { ENTERPROC(2, "DS SavePattern()");
if (_fPatternDirty && (dwFlags & SAVE_PATTERN_NAME)) { //
// Write out the pattern to the registry and INI files.
//
SystemParametersInfo(SPI_SETDESKPATTERN, 0, _szSelectedPattern, SPIF_UPDATEINIFILE); }
if (IsValidPattern(_szSelectedPattern) && (dwFlags & GENERATE_PATTERN_FILE)) { //
// Write out the pattern as a BMP file for use in HTML.
//
TCHAR szBitmapFile[MAX_PATH]; HANDLE hFileBitmap = INVALID_HANDLE_VALUE;
if (SUCCEEDED(GetPerUserFileName(szBitmapFile, ARRAYSIZE(szBitmapFile), PATTERN_FILENAME))) { hFileBitmap = CreateFile(szBitmapFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL); }
if (hFileBitmap != INVALID_HANDLE_VALUE) { DWORD cbWritten;
BITMAPFILEHEADER bmfh = {0}; bmfh.bfType = 0x4D42; // 'BM'
bmfh.bfSize = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD) + 8*sizeof(DWORD); bmfh.bfOffBits = sizeof(BITMAPFILEHEADER) + sizeof(BITMAPINFOHEADER) + 2*sizeof(RGBQUAD); WriteFile(hFileBitmap, &bmfh, sizeof(bmfh), &cbWritten, NULL);
BITMAPINFOHEADER bmih = {0}; bmih.biSize = sizeof(BITMAPINFOHEADER); bmih.biWidth = 8; bmih.biHeight = 8; bmih.biPlanes = 1; bmih.biBitCount = 1; bmih.biCompression = BI_RGB; WriteFile(hFileBitmap, &bmih, sizeof(bmih), &cbWritten, NULL);
RGBQUAD argbTable[2] = {0}; DWORD rgb; rgb = GetSysColor(COLOR_BACKGROUND); argbTable[0].rgbBlue = GetBValue(rgb); argbTable[0].rgbGreen = GetGValue(rgb); argbTable[0].rgbRed = GetRValue(rgb); rgb = GetSysColor(COLOR_WINDOWTEXT); argbTable[1].rgbBlue = GetBValue(rgb); argbTable[1].rgbGreen = GetGValue(rgb); argbTable[1].rgbRed = GetRValue(rgb); WriteFile(hFileBitmap, argbTable, sizeof(argbTable), &cbWritten, NULL);
DWORD adwBits[8]; PatternToDwords(_szSelectedPattern, adwBits); WriteFile(hFileBitmap, adwBits, sizeof(adwBits), &cbWritten, NULL);
CloseHandle(hFileBitmap); } }
EXITPROC(2, "DS SavePattern!"); }
void CActiveDesktop::_WriteHtmlFromString(LPCTSTR psz) { ENTERPROC(3, "DS WriteHtmlFromString(psz=>%s<)", psz); LPCWSTR pwsz; WCHAR szBuf[INTERNET_MAX_URL_LENGTH]; UINT uiLen; int cch;
if ((_pStream == NULL) && (_iDestFileCharset == ANSI_HTML_CHARSET)) { cch = SHUnicodeToAnsi(psz, (LPSTR)szBuf, ARRAYSIZE(szBuf)); ASSERT(cch == lstrlenW((LPWSTR)psz)+1); pwsz = (LPCWSTR)szBuf; uiLen = lstrlenA((LPSTR)szBuf); } else { pwsz = psz; uiLen = lstrlenW(pwsz); }
UINT cbWritten;
_WriteHtmlW(pwsz, uiLen, &cbWritten); EXITPROC(3, "DS WriteHtmlFromString!"); }
void CActiveDesktop::_WriteHtmlFromId(UINT uid) { ENTERPROC(3, "DS WriteHtmlFromId(uid=%d)", uid);
TCHAR szBuf[INTERNET_MAX_URL_LENGTH]; LoadString(HINST_THISDLL, uid, szBuf, ARRAYSIZE(szBuf)); _WriteHtmlFromString(szBuf);
EXITPROC(3, "DS WriteHtmlFromId!"); }
void CActiveDesktop::_WriteHtmlFromIdF(UINT uid, ...) { ENTERPROC(3, "DS WriteHtmlFromIdF(uid=%d,...)", uid);
TCHAR szBufFmt[INTERNET_MAX_URL_LENGTH]; TCHAR szBuf[INTERNET_MAX_URL_LENGTH];
LoadString(HINST_THISDLL, uid, szBufFmt, ARRAYSIZE(szBufFmt));
va_list arglist; va_start(arglist, uid); HRESULT hr = StringCchVPrintf(szBuf, ARRAYSIZE(szBuf), szBufFmt, arglist); va_end(arglist);
if (SUCCEEDED(hr)) { _WriteHtmlFromString(szBuf); }
EXITPROC(3, "DS WriteHtmlFromIdF!"); }
void CActiveDesktop::_WriteHtmlFromFile(LPCTSTR pszContents) { ENTERPROC(3, "DS WriteHtmlFromFile(pszContents=>%s<)", pszContents); CReadFileObj *pReadFileObj = new CReadFileObj(pszContents);
if (pReadFileObj) { if (pReadFileObj->_hFile != INVALID_HANDLE_VALUE) { WCHAR wcBuf[INTERNET_MAX_URL_LENGTH + 1]; UINT uiCharCount = ARRAYSIZE(wcBuf) -1; //Leave room for null termination.
UINT uiCharsRead; UINT uiCharsConverted; int iDestCharset = (_pStream ? UNICODE_HTML_CHARSET : _iDestFileCharset); while (SUCCEEDED(pReadFileObj->FileReadAndConvertChars(iDestCharset, wcBuf, uiCharCount, &uiCharsRead, &uiCharsConverted)) && uiCharsRead) { UINT cbWritten; _WriteHtmlW(wcBuf, uiCharsConverted, &cbWritten); if (uiCharsRead < uiCharCount) { break; } } } delete pReadFileObj; } EXITPROC(3, "DS WriteHtmlFromFile!"); }
void CActiveDesktop::_WriteHtmlFromReadFileObj(CReadFileObj *pFileObj, int iOffsetStart, int iOffsetEnd) { ENTERPROC(3, "DS WriteHtmlFromReadFileObj(pFileObj=%08X,iOffsetStart=%d,iOffsetEnd=%d)", pFileObj, iOffsetStart, iOffsetEnd);
if (iOffsetStart != -1) { pFileObj->FileSeekChars(iOffsetStart, FILE_BEGIN); } else { ASSERT(iOffsetEnd == -1); iOffsetEnd = -1; }
//Get the number of WIDECHARs to be written
UINT cchWrite = (iOffsetEnd == -1) ? 0xFFFFFFFF : (iOffsetEnd - iOffsetStart);
while (cchWrite) { WCHAR wcBuf[INTERNET_MAX_URL_LENGTH+1];
//
// Read a chunk.
//
UINT cchTryRead = (UINT)min(cchWrite, (ARRAYSIZE(wcBuf) - 1)); UINT cchActualRead; HRESULT hres;
//Note: if we are reading ANSI, we still use the unicode buff; but cast it!
if (_iDestFileCharset == ANSI_HTML_CHARSET) hres = pFileObj->FileReadCharsA((LPSTR)wcBuf, cchTryRead, &cchActualRead); else hres = pFileObj->FileReadCharsW(wcBuf, cchTryRead, &cchActualRead); if (SUCCEEDED(hres) && cchActualRead) { //
// Write a chunk.
//
UINT cchWritten; _WriteHtmlW(wcBuf, cchActualRead, &cchWritten); if (cchActualRead < cchTryRead) { //
// End of file, all done.
//
break; }
cchWrite -= cchActualRead; } else { //
// Error reading from file, all done.
//
break; } }
EXITPROC(3, "DS WriteHtmlFromHfile!"); }
int CActiveDesktop::_ScanForTagA(CReadFileObj *pFileObj, int iOffsetStart, LPCSTR pszTag) { ENTERPROC(2, "DS ScanForTagA(pFileObj=%08X,iOffsetStart=%d,pszTagA=>%s<)", pFileObj, iOffsetStart, pszTag);
int iRet = -1; BOOL fDoneReading = FALSE; int iOffset; DWORD cchTag = lstrlenA(pszTag);
pFileObj->FileSeekChars(iOffsetStart, FILE_BEGIN); iOffset = iOffsetStart;
DWORD cchBuf = 0; while (!fDoneReading) { char szBuf[INTERNET_MAX_URL_LENGTH+1];
//
// Fill in the buffer.
//
UINT cchTryRead = ARRAYSIZE(szBuf) - cchBuf - 1; UINT cchRead; if (SUCCEEDED(pFileObj->FileReadCharsA(&szBuf[cchBuf], cchTryRead, &cchRead)) && cchRead) { cchBuf += cchRead;
//
// Terminate the string.
//
szBuf[cchBuf] = '\0';
//
// Scan for the tag.
//
LPSTR pszTagInBuf = StrStrIA(szBuf, pszTag);
if (pszTagInBuf) { //
// Found the tag, compute the offset.
//
iRet = (int) (iOffset + pszTagInBuf - szBuf); fDoneReading = TRUE; } else if (cchRead < cchTryRead) { //
// Ran out of file without finding tag.
//
fDoneReading = TRUE; } else { //
// Compute how many bytes we want to throw away
// from this buffer so we can read in more data.
// We don't want to throw away all the bytes because
// the tag we want may span two buffers.
//
DWORD cchSkip = cchBuf - cchTag;
//
// Advance the file offset.
//
iOffset += cchSkip;
//
// Reduce the buffer size.
//
cchBuf -= cchSkip;
//
// Move the kept bytes to the beginning of the buffer.
//
MoveMemory(szBuf, szBuf + cchSkip, cchBuf * sizeof(szBuf[0])); } } else { fDoneReading = TRUE; } }
EXITPROC(2, "DS ScanForTagA=%d", iRet); return iRet; }
int CActiveDesktop::_ScanForTagW(CReadFileObj *pFileObj, int iOffsetStart, LPCWSTR pwszTag) { ENTERPROC(2, "DS ScanForTag(pFileObj=%08X,iOffsetStart=%d,pszTagA=>%s<)", pFileObj, iOffsetStart, pwszTag);
int iRet = -1; BOOL fDoneReading = FALSE; int iOffset; DWORD cchTag = lstrlenW(pwszTag);
pFileObj->FileSeekChars(iOffsetStart, FILE_BEGIN); iOffset = iOffsetStart;
DWORD cchBuf = 0; while (!fDoneReading) { WCHAR wszBuf[INTERNET_MAX_URL_LENGTH+1];
//
// Fill in the buffer.
//
UINT cchTryRead = ARRAYSIZE(wszBuf) - cchBuf - 1; UINT cchRead; if (SUCCEEDED(pFileObj->FileReadCharsW(&wszBuf[cchBuf], cchTryRead, &cchRead)) && cchRead) { cchBuf += cchRead;
//
// Terminate the string.
//
wszBuf[cchBuf] = L'\0';
//
// Scan for the tag.
//
LPWSTR pwszTagInBuf = StrStrIW(wszBuf, pwszTag);
if (pwszTagInBuf) { //
// Found the tag, compute the offset.
//
iRet = (int) (iOffset + pwszTagInBuf - wszBuf); fDoneReading = TRUE; } else if (cchRead < cchTryRead) { //
// Ran out of file without finding tag.
//
fDoneReading = TRUE; } else { //
// Compute how many bytes we want to throw away
// from this buffer so we can read in more data.
// We don't want to throw away all the bytes because
// the tag we want may span two buffers.
//
DWORD cchSkip = cchBuf - cchTag;
//
// Advance the file offset.
//
iOffset += cchSkip;
//
// Reduce the buffer size.
//
cchBuf -= cchSkip;
//
// Move the kept bytes to the beginning of the buffer.
//
MoveMemory(wszBuf, wszBuf + cchSkip, cchBuf*sizeof(wszBuf[0])); } } else { fDoneReading = TRUE; } }
EXITPROC(2, "DS ScanForTag=%d", iRet); return iRet; }
int CActiveDesktop::_ScanTagEntriesA(CReadFileObj *pReadFileObj, int iOffsetStart, TAGENTRYA *pte, int cte) { ENTERPROC(2, "DS ScanTagEntriesA(pReadFileObj=%08X,iOffsetStart=%d,pte=%08X,cte=%d)", pReadFileObj, iOffsetStart, pte, cte);
int iRet = -1; int i;
for (i=0; i<cte; i++,pte++) { iRet = _ScanForTagA(pReadFileObj, iOffsetStart, pte->pszTag); if (iRet != -1) { if (pte->fSkipPast) { iRet += lstrlenA(pte->pszTag); } break; } }
EXITPROC(2, "DS ScanTagEntriesA=%d", iRet); return iRet; }
int CActiveDesktop::_ScanTagEntriesW(CReadFileObj *pReadFileObj, int iOffsetStart, TAGENTRYW *pte, int cte) { ENTERPROC(2, "DS ScanTagEntriesW(pReadFileObj=%08X,iOffsetStart=%d,pte=%08X,cte=%d)", pReadFileObj, iOffsetStart, pte, cte);
int iRet = -1; int i;
for (i=0; i<cte; i++,pte++) { iRet = _ScanForTagW(pReadFileObj, iOffsetStart, pte->pwszTag); if (iRet != -1) { if (pte->fSkipPast) { iRet += lstrlenW(pte->pwszTag); } break; } }
EXITPROC(2, "DS ScanTagEntriesW=%d", iRet); return iRet; }
void CActiveDesktop::_ParseAnsiInputHtmlFile( LPTSTR szSelectedWallpaper, int *piOffsetBase, int *piOffsetComp) { //
// Figure out where to insert the base href tag.
//
int iOffsetBase = 0, iBaseTagStart; BOOL fUseBaseHref; LONG lOffsetDueToBOM = 0; //Character Offset due to the Byte Order Mark.
//1 for UNICODE and 0 for ANSI files.
// 98/11/11 #248047 vtan: This code looks for a <BASE HREF=...> tag.
// It used to use a scan for "<BASE" and assume that this was the
// desired tag. HTML allows a "<BASEFONT>" tag which was being
// mistaken for a "<BASE HREF=...>" tag. The code now looks for the
// same string but looks at the character following the "<BASE" to
// see if it's a white-space character.
fUseBaseHref = TRUE; _pReadFileObjHtmlBkgd->FileGetCurCharOffset(&lOffsetDueToBOM); iOffsetBase = (int)lOffsetDueToBOM; iBaseTagStart = _ScanForTagA(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, "<BASE"); if (iBaseTagStart != -1) { UINT uiCountChars, uiTryToRead; char szBaseTagBuffer[6+1]; // allow for "<BASEx" plus a NULL.
_pReadFileObjHtmlBkgd->FileSeekChars(iBaseTagStart, FILE_BEGIN); uiTryToRead = ARRAYSIZE(szBaseTagBuffer) - 1; if (SUCCEEDED(_pReadFileObjHtmlBkgd->FileReadCharsA(szBaseTagBuffer, uiTryToRead, &uiCountChars)) && uiCountChars) { char ch;
ch = szBaseTagBuffer[5]; fUseBaseHref = ((ch != ' ') && (ch != '\r') && (ch != '\n') && // this covers the UNIX line break scheme
(ch != '\t')); } } if (fUseBaseHref) { TAGENTRYA rgteBase[] = { { "<HEAD>", TRUE, }, { "<BODY", FALSE, }, { "<HTML>", TRUE, }, }; iOffsetBase = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, rgteBase, ARRAYSIZE(rgteBase)); if (iOffsetBase == -1) { iOffsetBase = (int)lOffsetDueToBOM; } }
//
// Figure out where to insert the components.
//
TAGENTRYA rgteComponents[] = { { "</BODY>", FALSE, }, { "</HTML>", FALSE, }, }; int iOffsetComponents = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, iOffsetBase, rgteComponents, ARRAYSIZE(rgteComponents));
//
// Write out the initial HTML up to the <HEAD> tag.
//
_WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, iOffsetBase);
//
// Write out the base tag.
//
if (fUseBaseHref) { //BASE tag must point to the base "URL". So, don't strip out the filename.
_WriteHtmlFromIdF(IDS_BASE_TAG, szSelectedWallpaper); }
// Figure out where to insert the DIV clause
TAGENTRYA rgteBodyStart[] = { { "<BODY", FALSE, }, }; int iOffsetBodyStart = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, iOffsetBase, rgteBodyStart, ARRAYSIZE(rgteBodyStart)); // Write out HTML until after the <BODY ......>
if (iOffsetBodyStart == -1) { // the <BODY> tag is not found, so we need to insert it.
// Copy over stuff until </HEAD>
TAGENTRYA rgteHeadEnd[] = { { "</HEAD>", TRUE, }, }; int iOffsetHeadEnd = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, iOffsetBase, rgteHeadEnd, ARRAYSIZE(rgteHeadEnd)); if (iOffsetHeadEnd != -1) { _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetHeadEnd); iOffsetBase = iOffsetHeadEnd; } _WriteHtmlFromIdF(IDS_BODY_CENTER_WP2); // "<BODY>"
_fNeedBodyEnd = TRUE; } else { TAGENTRYA rgteBodyEnd[] = { { ">", TRUE, }, }; int iOffsetBodyEnd = _ScanTagEntriesA(_pReadFileObjHtmlBkgd, iOffsetBodyStart, rgteBodyEnd, ARRAYSIZE(rgteBodyEnd)); if (iOffsetBodyEnd == -1) { // An error in the HTML.
iOffsetBodyEnd = iOffsetBodyStart; // FEATURE: We need a better recovery idea.
} _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetBodyEnd); iOffsetBase = iOffsetBodyEnd; }
*piOffsetBase = iOffsetBase; *piOffsetComp = iOffsetComponents; }
void CActiveDesktop::_GenerateHtmlHeader(void) { ENTERPROC(2, "DS GenerateHtmlHeader()");
EnumMonitorsArea ema; GetMonitorSettings(&ema);
RECT rcViewAreas[LV_MAX_WORKAREAS]; // WorkArea minus toolbar/tray areas
int nViewAreas = ARRAYSIZE(rcViewAreas); // Get the ViewAreas
if (!GetViewAreas(rcViewAreas, &nViewAreas)) { nViewAreas = 0; }
//Assume that the final Deskstat.htt that we generate is going to be in UNICODE.
//This will change to ANSI only if the background html wallpaper is ANSI (determined later)
_iDestFileCharset = UNICODE_HTML_CHARSET; //
// Write out the background and color.
//
TCHAR szSelectedWallpaper[INTERNET_MAX_URL_LENGTH]; // If the wallpaper does not have a directory specified (this may happen if other apps. change this value),
// we have to figure it out.
if (!GetWallpaperWithPath(_szSelectedWallpaper, szSelectedWallpaper, ARRAYSIZE(szSelectedWallpaper))) { return; // gross, but probably cleanest way
} BOOL fValidWallpaper = GetFileAttributes(szSelectedWallpaper) != 0xFFFFFFFF; if (_fSingleItem || IsWallpaperPicture(szSelectedWallpaper) || !fValidWallpaper) { //
// Write the BOM for UNICODE
//
if (_hFileHtml) { DWORD cbWritten; WriteFile(_hFileHtml, (LPCSTR)&wUnicodeBOM, sizeof(wUnicodeBOM), &cbWritten, NULL); } // To account for the vagaries of the desktop browser (it's TopLeft starts from the TopLeft
// of the Desktop ViewArea instead of the TopLeft of the monitor, as might be expected)
// which happens only in the case of one active monitor systems, we add the width of the
// tray/toolbars to the co-ordinates of the DIV section of each monitor's wallpaper.
int iLeft, iTop; if (nViewAreas == 1) { iLeft = rcViewAreas[0].left - ema.rcVirtualMonitor.left; iTop = rcViewAreas[0].top - ema.rcVirtualMonitor.top; } else { iLeft = 0; iTop = 0; }
//
// Write out the standard header.
//
UINT i; for (i=IDS_COMMENT_BEGIN; i<IDS_BODY_BEGIN; i++) { _WriteHtmlFromIdF(i); }
//
// Write out the body tag, with background bitmap.
//
DWORD rgbDesk; rgbDesk = GetSysColor(COLOR_DESKTOP);
TCHAR szBitmapFile[MAX_PATH]; if (FAILED(GetPerUserFileName(szBitmapFile, ARRAYSIZE(szBitmapFile), PATTERN_FILENAME))) { szBitmapFile[0] = 0; }
if (!_fSingleItem && _szSelectedWallpaper[0] && fValidWallpaper) { TCHAR szWallpaperUrl[INTERNET_MAX_URL_LENGTH]; DWORD cch = ARRAYSIZE(szWallpaperUrl); UrlCreateFromPath(szSelectedWallpaper, szWallpaperUrl, &cch, URL_INTERNAL_PATH);
switch (_wpo.dwStyle) { case WPSTYLE_TILE: //
// Ignore the pattern, tile the wallpaper as background.
//
_WriteHtmlFromIdF(IDS_BODY_BEGIN2, szWallpaperUrl, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk)); break;
case WPSTYLE_CENTER: if (IsValidPattern(_szSelectedPattern)) { //
// Tile the pattern as the main background.
//
_WriteHtmlFromIdF(IDS_BODY_BEGIN2, szBitmapFile, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk)); if (_fBackgroundHtml) // We are generating the HTML for preview
{ _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP, szWallpaperUrl); } else { //
// Write out a DIV section for a centered, untiled wallpaper.
//
// write it out for each monitor.
for(int i = 0; i < ema.iMonitors; i++) { _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP2, ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft, ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop, ema.rcMonitor[i].right - ema.rcMonitor[i].left, ema.rcMonitor[i].bottom - ema.rcMonitor[i].top, szWallpaperUrl); } } } else { //
// Write out a non-tiled, centered wallpaper as background.
//
if (_fBackgroundHtml) // We are generating the HTML for preview
{ _WriteHtmlFromIdF(IDS_BODY_CENTER_WP, szWallpaperUrl, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk)); } else { _WriteHtmlFromIdF(IDS_BODY_CENTER_WP2, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk)); // write it out for each monitor.
for(int i = 0; i < ema.iMonitors; i++) { _WriteHtmlFromIdF(IDS_BODY_PATTERN_AND_WP2, ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft, ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop, ema.rcMonitor[i].right - ema.rcMonitor[i].left, ema.rcMonitor[i].bottom - ema.rcMonitor[i].top, szWallpaperUrl); } } } break;
case WPSTYLE_STRETCH: //
// Ignore the pattern, create a DIV section of the wallpaper
// stretched to 100% of the screen.
//
_WriteHtmlFromIdF(IDS_BODY_BEGIN2, c_szNULL, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk)); if (_fBackgroundHtml) // We are generating the HTML for preview
{ _WriteHtmlFromIdF(IDS_STRETCH_WALLPAPER, szWallpaperUrl); } else { // stretch it for each monitor.
for(int i = 0; i < ema.iMonitors; i++) { _WriteHtmlFromIdF(IDS_DIV_START3, ema.rcMonitor[i].left - ema.rcVirtualMonitor.left - iLeft, ema.rcMonitor[i].top - ema.rcVirtualMonitor.top - iTop, ema.rcMonitor[i].right - ema.rcMonitor[i].left, ema.rcMonitor[i].bottom - ema.rcMonitor[i].top); _WriteHtmlFromIdF(IDS_STRETCH_WALLPAPER, szWallpaperUrl); _WriteHtmlFromId(IDS_DIV_END); } } break; } } else { //
// Ignore the wallpaper, generate either a tiled pattern
// or solid color background.
//
_WriteHtmlFromIdF(IDS_BODY_BEGIN2, !_fSingleItem && IsValidPattern(_szSelectedPattern) ? szBitmapFile : c_szNULL, GetRValue(rgbDesk), GetGValue(rgbDesk), GetBValue(rgbDesk)); } } else { if ((_pReadFileObjHtmlBkgd = new CReadFileObj(szSelectedWallpaper)) && (_pReadFileObjHtmlBkgd->_hFile != INVALID_HANDLE_VALUE)) { //The final Desktop.htt will be in ANSI only if the source html file is also in ansi.
//So, get the type from the selected wallpaper object.
_iDestFileCharset = _pReadFileObjHtmlBkgd->_iCharset; //
// Write the BOM for UNICODE
//
if (_hFileHtml && (_iDestFileCharset == UNICODE_HTML_CHARSET)) { DWORD cbWritten; WriteFile(_hFileHtml, (LPCSTR)&wUnicodeBOM, sizeof(wUnicodeBOM), &cbWritten, NULL); } //
// Figure out where to insert the base href tag.
//
int iOffsetBase = 0; int iOffsetComponents; // 98/11/11 #248047 vtan: This code looks for a <BASE HREF=...> tag.
// It used to use a scan for "<BASE" and assume that this was the
// desired tag. HTML allows a "<BASEFONT>" tag which was being
// mistaken for a "<BASE HREF=...>" tag. The code now looks for the
// same string but looks at the character following the "<BASE" to
// see if it's a white-space character.
if (_iDestFileCharset == ANSI_HTML_CHARSET) { //The following function parses the ANSI input html file and finds various offsets
_ParseAnsiInputHtmlFile(szSelectedWallpaper, &iOffsetBase, &iOffsetComponents); } else { //The following code parses the UNICODE input html wallpaper file.
int iBaseTagStart; BOOL fUseBaseHref; LONG lOffsetDueToBOM = 0; //Character Offset due to the Byte Order Mark.
//1 for UNICODE and 0 for ANSI files.
fUseBaseHref = TRUE; _pReadFileObjHtmlBkgd->FileGetCurCharOffset(&lOffsetDueToBOM); iOffsetBase = (int)lOffsetDueToBOM; iBaseTagStart = _ScanForTagW(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, L"<BASE"); if (iBaseTagStart != -1) { UINT uiCountChars, uiTryToRead; WCHAR wszBaseTagBuffer[6+1]; // allow for "<BASEx" plus a NULL.
_pReadFileObjHtmlBkgd->FileSeekChars(iBaseTagStart, FILE_BEGIN); uiTryToRead = ARRAYSIZE(wszBaseTagBuffer) - 1; if (SUCCEEDED(_pReadFileObjHtmlBkgd->FileReadCharsW(wszBaseTagBuffer, uiTryToRead, &uiCountChars)) && uiCountChars) { WCHAR wc;
wc = wszBaseTagBuffer[5]; fUseBaseHref = ((wc != L' ') && (wc != L'\r') && (wc != L'\n') && // this covers the UNIX line break scheme
(wc != L'\t')); } } if (fUseBaseHref) { TAGENTRYW rgteBase[] = { { L"<HEAD>", TRUE, }, { L"<BODY", FALSE, }, { L"<HTML>", TRUE, }, }; iOffsetBase = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, rgteBase, ARRAYSIZE(rgteBase)); if (iOffsetBase == -1) { iOffsetBase = (int)lOffsetDueToBOM; } }
//
// Figure out where to insert the components.
//
TAGENTRYW rgteComponents[] = { { L"</BODY>", FALSE, }, { L"</HTML>", FALSE, }, }; iOffsetComponents = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, iOffsetBase, rgteComponents, ARRAYSIZE(rgteComponents));
//
// Write out the initial HTML up to the <HEAD> tag.
//
_WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, (int)lOffsetDueToBOM, iOffsetBase);
//
// Write out the base tag.
//
if (fUseBaseHref) { //BASE tag must point to the base "URL". So, don't strip out the filename.
_WriteHtmlFromIdF(IDS_BASE_TAG, szSelectedWallpaper); }
// Figure out where to insert the DIV clause
TAGENTRYW rgteBodyStart[] = { { L"<BODY", FALSE, }, }; int iOffsetBodyStart = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, iOffsetBase, rgteBodyStart, ARRAYSIZE(rgteBodyStart)); // Write out HTML until after the <BODY ......>
if (iOffsetBodyStart == -1) { // the <BODY> tag is not found, so we need to insert it.
// Copy over stuff until </HEAD>
TAGENTRYW rgteHeadEnd[] = { { L"</HEAD>", TRUE, }, }; int iOffsetHeadEnd = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, iOffsetBase, rgteHeadEnd, ARRAYSIZE(rgteHeadEnd)); if (iOffsetHeadEnd != -1) { _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetHeadEnd); iOffsetBase = iOffsetHeadEnd; } _WriteHtmlFromIdF(IDS_BODY_CENTER_WP2); // "<BODY>"
_fNeedBodyEnd = TRUE; } else { TAGENTRYW rgteBodyEnd[] = { { L">", TRUE, }, }; int iOffsetBodyEnd = _ScanTagEntriesW(_pReadFileObjHtmlBkgd, iOffsetBodyStart, rgteBodyEnd, ARRAYSIZE(rgteBodyEnd)); if (iOffsetBodyEnd == -1) { // An error in the HTML.
iOffsetBodyEnd = iOffsetBodyStart; // FEATURE: We need a better recovery idea.
} _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetBodyEnd); iOffsetBase = iOffsetBodyEnd; }
} // Insert the DIV clause
if (ema.iMonitors > 1) { int iIndexPrimaryMonitor; HMONITOR hMonitorPrimary; MONITORINFO monitorInfo;
// 99/03/23 #275429 vtan: We used GetViewAreas() to fill in rcViewAreas above.
// The code here used to assume that [0] ALWAYS referred to the primary monitor.
// This isn't the case if the monitor settings are changed without a restart.
// In order to compensate for this and always render the wallpaper into the
// primary monitor, a search is performed to find a (left, top) that matches
// one of the work areas and this is used as the primary monitor. If none can
// be found then default to the old algorithm.
hMonitorPrimary = GetPrimaryMonitor(); monitorInfo.cbSize = sizeof(monitorInfo); TBOOL(GetMonitorInfo(hMonitorPrimary, &monitorInfo)); iIndexPrimaryMonitor = -1; for (int i = 0; (iIndexPrimaryMonitor < 0) && (i < nViewAreas); ++i) { if ((monitorInfo.rcWork.left == rcViewAreas[i].left) && (monitorInfo.rcWork.top == rcViewAreas[i].top)) { iIndexPrimaryMonitor = i; } } if (iIndexPrimaryMonitor < 0) iIndexPrimaryMonitor = 0; if ((nViewAreas <= 0) || (rcViewAreas[iIndexPrimaryMonitor].right == rcViewAreas[iIndexPrimaryMonitor].left)) // The second case could occur on bootup
{ // Some error occured when getting the ViewAreas. Recover from the error by using the workarea.
// Get the workarea of the primary monitor, since HTML wallpapers are displayed only there.
GetMonitorWorkArea(hMonitorPrimary, &rcViewAreas[iIndexPrimaryMonitor]); } _WriteHtmlFromIdF(IDS_DIV_START3, rcViewAreas[iIndexPrimaryMonitor].left - ema.rcVirtualMonitor.left, rcViewAreas[iIndexPrimaryMonitor].top - ema.rcVirtualMonitor.top, rcViewAreas[iIndexPrimaryMonitor].right - rcViewAreas[iIndexPrimaryMonitor].left, rcViewAreas[iIndexPrimaryMonitor].bottom - rcViewAreas[iIndexPrimaryMonitor].top); }
//
// Write out HTML from after <HEAD> tag to just before </BODY> tag.
//
_WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, iOffsetBase, iOffsetComponents);
if (ema.iMonitors > 1) { _WriteHtmlFromId(IDS_DIV_END); } } else { if (_pReadFileObjHtmlBkgd) delete _pReadFileObjHtmlBkgd; _pReadFileObjHtmlBkgd = NULL; } }
EXITPROC(2, "DS GenerateHtmlHeader!"); }
void CActiveDesktop::_WriteResizeable(COMPONENTA *pcomp) { TCHAR szResizeable[3];
//If Resize is set, then the comp is resizeable in both X and Y directions!
if (pcomp->cpPos.fCanResize || (pcomp->cpPos.fCanResizeX && pcomp->cpPos.fCanResizeY)) { szResizeable[0] = TEXT('X'); szResizeable[1] = TEXT('Y'); szResizeable[2] = TEXT('\0'); } else if (pcomp->cpPos.fCanResizeX) { szResizeable[0] = TEXT('X'); szResizeable[1] = TEXT('\0'); } else if (pcomp->cpPos.fCanResizeY) { szResizeable[0] = TEXT('Y'); szResizeable[1] = TEXT('\0'); }
_WriteHtmlFromIdF(IDS_RESIZEABLE, szResizeable); }
void CActiveDesktop::_WriteHtmlW(LPCWSTR wcBuf, UINT cchToWrite, UINT *pcchWritten) { ULONG cchWritten = 0; UINT uiSize; if (_pStream) { uiSize = sizeof(WCHAR); _pStream->Write((LPVOID)wcBuf, cchToWrite * uiSize, &cchWritten); } else { ASSERT(_hFileHtml); uiSize = (_iDestFileCharset == ANSI_HTML_CHARSET) ? sizeof(char) : sizeof(WCHAR); WriteFile(_hFileHtml, (LPCVOID)wcBuf, cchToWrite * uiSize, &cchWritten, NULL); } *pcchWritten = (UINT)(cchWritten/uiSize); //Convert to number of chars.
}
void CActiveDesktop::_GenerateHtmlPicture(COMPONENTA *pcomp) { ENTERPROC(2, "DS GenerateHtmlPicture(pcomp=%08X)");
//
// Write out the image src HTML.
//
TCHAR szUrl[INTERNET_MAX_URL_LENGTH]; DWORD cch = ARRAYSIZE(szUrl); HRESULT hr = UrlCreateFromPath(pcomp->szSource, szUrl, &cch, 0); if (FAILED(hr)) { hr = StringCchCopy(szUrl, ARRAYSIZE(szUrl), pcomp->szSource); }
if (SUCCEEDED(hr)) { _WriteHtmlFromIdF(IDS_IMAGE_BEGIN2, pcomp->dwID, szUrl);
//
// Write out whether this image is resizeable or not!
//
_WriteResizeable(pcomp);
//
// Write out the URL that must be used for subscription purposes.
//
_WriteHtmlFromIdF(IDS_SUBSCRIBEDURL, pcomp->szSubscribedURL);
//
// Write out the image location HTML.
//
if ((pcomp->cpPos.dwWidth == COMPONENT_DEFAULT_WIDTH) && (pcomp->cpPos.dwHeight == COMPONENT_DEFAULT_HEIGHT)) { _WriteHtmlFromIdF(IDS_IMAGE_LOCATION, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.izIndex); } else { _WriteHtmlFromIdF(IDS_IMAGE_SIZE, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.dwWidth, pcomp->cpPos.dwHeight, pcomp->cpPos.izIndex); } }
EXITPROC(2, "DS GenerateHtmlPicture!"); }
void CActiveDesktop::_GenerateHtmlDoc(COMPONENTA *pcomp) { ENTERPROC(2, "DS GenerateHtmlDoc(pcomp=%08X)"); TCHAR szUrl[INTERNET_MAX_URL_LENGTH]; DWORD dwSize = ARRAYSIZE(szUrl); LPTSTR lpszUrl = szUrl;
if (FAILED(UrlCreateFromPath(pcomp->szSource, szUrl, &dwSize, 0))) lpszUrl = pcomp->szSource;
//
// Write out the DIV header HTML.
//
_WriteHtmlFromIdF(IDS_DIV_START2, pcomp->dwID, lpszUrl);
//
// Write out whether this component is resizeable or not!
//
_WriteResizeable(pcomp);
//
// Write out the DIV location HTML.
//
_WriteHtmlFromIdF(IDS_DIV_SIZE, pcomp->cpPos.dwHeight, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.dwWidth, pcomp->cpPos.izIndex);
//
// Extract the doc contents directly into the HTML.
//
_WriteHtmlFromFile(pcomp->szSource);
//
// Close the DIV section.
//
_WriteHtmlFromId(IDS_DIV_END);
EXITPROC(2, "DS GenerateHtmlDoc!"); }
void CActiveDesktop::_GenerateHtmlSite(COMPONENTA *pcomp) { ENTERPROC(2, "DS GenerateHtmlSite(pcomp=%08X)");
//
// Write out the frame src HTML.
//
TCHAR szUrl[INTERNET_MAX_URL_LENGTH]; DWORD cch=ARRAYSIZE(szUrl); if (FAILED(UrlCreateFromPath(pcomp->szSource, szUrl, &cch, 0))) { if (FAILED(StringCchCopy(szUrl, ARRAYSIZE(szUrl), pcomp->szSource))) { return; } }
DWORD currentURLLength, maximumURLLength; LPTSTR pszURL = NULL; TCHAR szFormatBuffer[0x0100];
// 98/09/29 #211384 vtan: There is a limitation in wvsprintf.
// It only allows 2048 bytes in its buffer. If the URL is
// longer than 1024 characters less the IDS_IFRAME_BEGIN2
// string length less the component ID less "scrolling=no"
// if the component cannot be scrolled then the URL string
// will not be correctly inserted into the IDS_IFRAME_BEGIN2
// string and there will be a missing end-quote and trident
// will fail to render desktop.htt correctly.
// To correct against this the followING limits the length of
// the URL to this maximum and truncates any characters
// beyond the limit so that the IDS_IFRAME_BEGIN2 string
// contains its end-quote and trident does not barf.
// The above condition is a boundary condition and this
// check is quick so that the calculations that follow do
// not have to be executed repeatedly.
currentURLLength = lstrlen(szUrl); if (currentURLLength > 768) // a hard-coded limit
{ maximumURLLength = 1024; // wvsprintf limit
LoadString(HINST_THISDLL, IDS_IFRAME_BEGIN2, szFormatBuffer, ARRAYSIZE(szFormatBuffer)); maximumURLLength -= lstrlen(szFormatBuffer); // IDS_IFRAME_BEGIN2
maximumURLLength -= 16; // pcomp->dwID
maximumURLLength -= lstrlen(TEXT("scrolling=no")); // pcomp->fNoScroll
if (currentURLLength > maximumURLLength) szUrl[maximumURLLength] = static_cast<TCHAR>('\0'); } _WriteHtmlFromIdF(IDS_IFRAME_BEGIN2, pcomp->dwID, szUrl, pcomp->fNoScroll ? TEXT("scrolling=no") : c_szNULL);
//
// Write out whether this Component is resizeable or not!
//
_WriteResizeable(pcomp);
// 98/09/29 #211384 vtan: See above.
currentURLLength = lstrlen(pcomp->szSubscribedURL); if (currentURLLength > 768) { if (SUCCEEDED(StringCchCopy(szUrl, ARRAYSIZE(szUrl), pcomp->szSubscribedURL))) { maximumURLLength = 1024; LoadString(HINST_THISDLL, IDS_SUBSCRIBEDURL, szFormatBuffer, ARRAYSIZE(szFormatBuffer)); maximumURLLength -= lstrlen(szFormatBuffer); // IDS_SUBSCRIBEDURL
if (currentURLLength > maximumURLLength) szUrl[maximumURLLength] = static_cast<TCHAR>('\0'); pszURL = szUrl; } } else { pszURL = pcomp->szSubscribedURL; }
if (pszURL) { //
// Write out the URL that must be used for subscription purposes.
//
_WriteHtmlFromIdF(IDS_SUBSCRIBEDURL, pszURL);
//
// Write out the frame location HTML.
//
_WriteHtmlFromIdF(IDS_IFRAME_SIZE, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.dwWidth, pcomp->cpPos.dwHeight, pcomp->cpPos.izIndex); }
EXITPROC(2, "DS GenerateHtmlSite!"); }
void CActiveDesktop::_GenerateHtmlControl(COMPONENTA *pcomp) { ENTERPROC(2, "DS GenerateHtmlControl(pcomp=%08X)"); ASSERT(pcomp); // Did the Administrator restrict "Channel UI"?
if (SHRestricted2W(REST_NoChannelUI, NULL, 0)) { TCHAR szChannelOCGUID[GUIDSTR_MAX];
SHStringFromGUID(CLSID_ChannelOC, szChannelOCGUID, ARRAYSIZE(szChannelOCGUID)); if (!StrCmpNI(pcomp->szSource, &(szChannelOCGUID[1]), lstrlen(pcomp->szSource)-3)) { // Yes, so we need to hide the Channel Desktop Component.
// Return here before we generate it.
return; } } //
// Write out the control HTML.
//
// First the control header
_WriteHtmlFromIdF(IDS_CONTROL_1, pcomp->dwID); // then the size
_WriteHtmlFromIdF(IDS_CONTROL_2, pcomp->cpPos.dwHeight, _fSingleItem ? 0 : pcomp->cpPos.iLeft, _fSingleItem ? 0 : pcomp->cpPos.iTop, pcomp->cpPos.dwWidth, pcomp->cpPos.izIndex); //
// Write out whether this Control is resizeable or not!
//
_WriteResizeable(pcomp);
// Finally the rest of the control
_WriteHtmlFromIdF(IDS_CONTROL_3, pcomp->szSource);
EXITPROC(2, "DS GenerateHtmlControl!"); }
void CActiveDesktop::_GenerateHtmlComponent(COMPONENTA *pcomp) { ENTERPROC(2, "DS GenerateHtmlComponent(pcomp=%08X)");
switch(pcomp->iComponentType) { case COMP_TYPE_PICTURE: _GenerateHtmlPicture(pcomp); break;
case COMP_TYPE_HTMLDOC: _GenerateHtmlDoc(pcomp); break;
case COMP_TYPE_WEBSITE: _GenerateHtmlSite(pcomp); break;
case COMP_TYPE_CONTROL: _GenerateHtmlControl(pcomp); break; }
EXITPROC(2, "DS GenerateHtmlComponent!"); }
void CActiveDesktop::_GenerateHtmlFooter(void) { ENTERPROC(2, "DS GenerateHtmlFooter()");
//
// Write out the deskmovr object.
//
if (!_fNoDeskMovr) { TCHAR szDeskMovrFile[MAX_PATH];
if (GetWindowsDirectory(szDeskMovrFile, ARRAYSIZE(szDeskMovrFile)) && PathAppend(szDeskMovrFile, DESKMOVR_FILENAME)) { _WriteHtmlFromFile(szDeskMovrFile); } }
//
// Write out the concluding HTML tags.
//
if (_pReadFileObjHtmlBkgd) { if (_fNeedBodyEnd) { // We had introduced the <BODY> tag by ourselves.
_WriteHtmlFromId(IDS_BODY_END2); _fNeedBodyEnd = FALSE; } _WriteHtmlFromReadFileObj(_pReadFileObjHtmlBkgd, -1, -1); delete _pReadFileObjHtmlBkgd; //Close the file and cleanup!
_pReadFileObjHtmlBkgd = NULL; } else { _WriteHtmlFromId(IDS_BODY_END); }
EXITPROC(2, "DS GenerateHtmlFooter!"); }
void CActiveDesktop::_GenerateHtml(void) { ENTERPROC(2, "DS GenerateHtml()");
TCHAR szHtmlFile[MAX_PATH];
//
// Compute the filename.
//
szHtmlFile[0] = TEXT('\0');
if (SUCCEEDED(GetPerUserFileName(szHtmlFile, ARRAYSIZE(szHtmlFile), DESKTOPHTML_FILENAME))) { // Recreate the file.
_hFileHtml = CreateFile(szHtmlFile, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_HIDDEN | FILE_ATTRIBUTE_SYSTEM, NULL); if (_hFileHtml != INVALID_HANDLE_VALUE) { _GenerateHtmlHeader();
if (_co.fEnableComponents && _hdsaComponent && DSA_GetItemCount(_hdsaComponent) && !SHRestricted(REST_NODESKCOMP)) { int i;
for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++) { COMPONENTA comp; comp.dwSize = sizeof(COMPONENTA);
if ((DSA_GetItem(_hdsaComponent, i, &comp) != -1) && (comp.fChecked)) { _GenerateHtmlComponent(&comp); } } }
_GenerateHtmlFooter(); CloseHandle(_hFileHtml); SetDesktopFlags(COMPONENTS_DIRTY, 0); } else {
// 99/05/19 #340772 vtan: If unable to open desktop.htt it's probably
// in use by another process or task (perhaps trident is trying to
// render it). In this case mark it dirty so that it will get recreated
// - yet again but this time with more current data.
SetDesktopFlags(COMPONENTS_DIRTY, COMPONENTS_DIRTY); } }
EXITPROC(2, "DS GenerateHtml!"); }
HRESULT CActiveDesktop::GenerateDesktopItemHtml(LPCWSTR pwszFileName, COMPONENT *pcomp, DWORD dwReserved) { HRESULT hres = E_FAIL; ENTERPROC(2, "DS GenerateComponentHtml(pcomp=%08X)", pcomp);
//Check for the input parameters
if (!pwszFileName || (pcomp && (pcomp->dwSize != sizeof(*pcomp)) && (pcomp->dwSize != sizeof(IE4COMPONENT)))) return E_INVALIDARG;
ASSERT(!dwReserved); // These should be 0
//
// Create the file.
//
_hFileHtml = CreateFile(pwszFileName, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL); if (_hFileHtml != INVALID_HANDLE_VALUE) { _fNoDeskMovr = TRUE; _fBackgroundHtml = TRUE; //Check if we need to add a component
if (pcomp) { COMPONENTA CompA;
CompA.dwSize = sizeof(CompA); WideCompToMultiComp(pcomp, &CompA);
_fSingleItem = TRUE; _GenerateHtmlHeader();
_GenerateHtmlComponent(&CompA); _GenerateHtmlFooter(); _fSingleItem = FALSE; } else { //generate just the header and the footer with proper
// wallpaper and pattern info!
_GenerateHtmlHeader(); _GenerateHtmlFooter(); } _fBackgroundHtml = FALSE; _fNoDeskMovr = FALSE;
CloseHandle(_hFileHtml);
hres = S_OK; } _hFileHtml = NULL;
EXITPROC(2, "DS GenerateComponentHtml=%d", hres); return hres; }
//
// AddUrl
//
//
HRESULT CActiveDesktop::AddUrl(HWND hwnd, LPCWSTR pszSourceW, LPCOMPONENT pcomp, DWORD dwFlags) { LPTSTR pszExt; HRESULT fOkay = TRUE; BOOL fExtIsCdf,fPathIsUrl; BOOL fSubscribed = FALSE; COMPONENT compLocal; COMPONENTA compA; TCHAR szSource[INTERNET_MAX_URL_LENGTH];
// 98/08/28 vtan #202777: The following if statement sanitizes parameters
// passed to AddUrl(). The statements following the "||" are executed
// despite the for pcomp against NULL. This causes an access violation
// and an exception to be thrown.
#if 0
//Check for the input parameters.
if (!pszSourceW || (pcomp && ((pcomp->dwSize != sizeof(*pcomp)) && (pcomp->dwSize != sizeof(IE4COMPONENT))) || ((pcomp->dwSize == sizeof(*pcomp)) && !VALIDATESTATE(pcomp->dwCurItemState)))) return E_INVALIDARG; #else
// The following performs the same comparison but is spread into three
// separate comparisons. As performance is not a critical issue here
// but correctness is this makes the tests clear and understandable.
// The invalid conditions are described.
// Validate input parameters. Invalid parameters are:
// 1) NULL pszSourceW
// 2) pcomp->dwSize for a COMPONENT struct but invalid pcomp->dwCurItemState
// 3) pcomp->dwSize is not for a COMPONENT struct nor for a IE4COMPONENT struct
if (pszSourceW == NULL) return(E_INVALIDARG); if (pcomp != NULL) { if ((pcomp->dwSize == sizeof(*pcomp)) && !VALIDATESTATE(pcomp->dwCurItemState)) return(E_INVALIDARG); if ((pcomp->dwSize != sizeof(*pcomp)) && (pcomp->dwSize != sizeof(IE4COMPONENT))) return(E_INVALIDARG); } #endif
// Catch folks that call our API's to add components and prevent them from doing
// so if the restriction is in place.
if (SHIsRestricted(NULL, REST_NOADDDESKCOMP)) return E_ACCESSDENIED;
if (!pcomp) { pcomp = &compLocal; pcomp->dwSize = sizeof(compLocal); pcomp->dwCurItemState = IS_NORMAL; }
// Attempt to come up with a reasonable window handle if none is passed in. ParseDesktopComponent
// will fail to attempt to create a subscription if a NULL window handle is passed in.
if (!hwnd) hwnd = GetLastActivePopup(GetActiveWindow());
compA.dwSize = sizeof(compA); compA.dwCurItemState = (pcomp->dwSize != sizeof(IE4COMPONENT)) ? pcomp->dwCurItemState : IS_NORMAL;
SHUnicodeToTChar(pszSourceW, szSource, ARRAYSIZE(szSource)); pszExt = PathFindExtension(szSource); fExtIsCdf = lstrcmpi(pszExt, TEXT(".CDF")) == 0; fPathIsUrl = PathIsURL(szSource) && !UrlIsFileUrl(szSource);
if (FindComponent(szSource, (g_pActiveDesk ? g_pActiveDesk : this))) { if (dwFlags & ADDURL_SILENT) { if (FAILED(StringCchCopy(compA.szSource, ARRAYSIZE(compA.szSource), szSource))) { compA.szSource[0] = 0; }
MultiCompToWideComp(&compA, pcomp); RemoveDesktopItem(pcomp, 0); } else { // This is a long string. So,...
TCHAR szMsg[512]; TCHAR szMsg2[256]; TCHAR szTitle[128]; LoadString(HINST_THISDLL, IDS_COMP_EXISTS, szMsg, ARRAYSIZE(szMsg)); LoadString(HINST_THISDLL, IDS_COMP_EXISTS_2, szMsg2, ARRAYSIZE(szMsg2)); StringCchCat(szMsg, ARRAYSIZE(szMsg), szMsg2); // display, truncation fine
LoadString(HINST_THISDLL, IDS_COMP_TITLE, szTitle, ARRAYSIZE(szTitle)); MessageBox(hwnd, szMsg, szTitle, MB_OK);
fOkay = FALSE; } }
if (fOkay && CheckForExistingSubscription(szSource)) { if ((dwFlags & ADDURL_SILENT) || (ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_COMP_SUBSCRIBED), MAKEINTRESOURCE(IDS_COMP_TITLE), MB_YESNO) == IDYES)) { DeleteFromSubscriptionList(szSource); } else { fOkay = FALSE; } }
if (fOkay) { if (fPathIsUrl || fExtIsCdf) { HRESULT hr; IProgressDialog * pProgressDlg = NULL; DECLAREWAITCURSOR;
// 98/12/16 vtan #250938: Cannot add new components that are not
// local with ICW run to completion. Tell the user and launch ICW.
if (!IsICWCompleted()) { if ((dwFlags & ADDURL_SILENT) == 0) { ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_COMP_ICW_ADD), MAKEINTRESOURCE(IDS_COMP_ICW_TITLE), MB_OK); LaunchICW(); } fOkay = FALSE; } else { SetWaitCursor(); // ParseDesktopComponent can hang for a long time, we need some sort of progress
// UI up before we call it.
if (!(dwFlags & ADDURL_SILENT) && !fExtIsCdf) { if (pProgressDlg = CProgressDialog_CreateInstance(IDS_COMP_TITLE, IDA_ISEARCH, g_hinst)) { TCHAR szConnecting[80]; LoadString(HINST_THISDLL, IDS_CONNECTING, szConnecting, ARRAYSIZE(szConnecting)); pProgressDlg->SetLine(1, szConnecting, FALSE, NULL); pProgressDlg->SetLine(2, szSource, TRUE, NULL); pProgressDlg->StartProgressDialog(hwnd, NULL, PROGDLG_AUTOTIME | PROGDLG_NOPROGRESSBAR, NULL); } }
hr = ParseDesktopComponent(hwnd, szSource, pcomp);
if (pProgressDlg) { pProgressDlg->StopProgressDialog(); fOkay = !pProgressDlg->HasUserCancelled(); // User may have cancelled the progress dialog
pProgressDlg->Release(); } ResetWaitCursor();
if (hr == S_FALSE) // User cancelled operation via subscription download dialog
fOkay = FALSE;
if (fOkay) { if (SUCCEEDED(hr)) { //
// Convert ed's wide thinggy to multi.
//
WideCompToMultiComp(pcomp, &compA); fSubscribed = TRUE; } else if (!fExtIsCdf) { //
// This is some non-CDF url.
//
CreateComponent(&compA, szSource); } else { //
// We barfed on a CDF, bring up an error message.
//
if (!(dwFlags & ADDURL_SILENT)) { ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_COMP_BADURL), MAKEINTRESOURCE(IDS_COMP_TITLE), MB_OK); } fOkay = FALSE; } } } } else { //
// This is just some local file.
//
CreateComponent(&compA, szSource); } }
if (fOkay && fPathIsUrl && !fSubscribed) { //
// Run subscription code on URLs if CDF code hasn't already.
//
if (dwFlags & ADDURL_SILENT) { ISubscriptionMgr *psm;
if (SUCCEEDED(CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&psm))) { //We need to zero init this structure except the cbSize field.
SUBSCRIPTIONINFO siDefault = {sizeof(SUBSCRIPTIONINFO)}; //This field is already initialized above.
//siDefault.cbSize = sizeof(siDefault);
psm->CreateSubscription(hwnd, szSource, szSource, CREATESUBS_NOUI, SUBSTYPE_DESKTOPURL, &siDefault); psm->UpdateSubscription(szSource); psm->Release(); } } else { HRESULT hres = CreateSubscriptionsWizard(SUBSTYPE_DESKTOPURL, szSource, NULL, hwnd); if (!SUCCEEDED(hres)) //Some error, or the user chose Cancel - we should fail.
{ ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_COMP_BADSUBSCRIBE), MAKEINTRESOURCE(IDS_COMP_TITLE), MB_OK); } fOkay = (hres == S_OK); //could be S_FALSE, which means CreateSubscription was cancelled
//so we don't display the above error, but we don't create the DTI
} }
MultiCompToWideComp(&compA, pcomp); if (fOkay) { AddDesktopItem(pcomp, 0); return S_OK; } else { return E_FAIL; } }
void CActiveDesktop::_SaveSettings(DWORD dwFlags) { ENTERPROC(2, "DS SaveSettings()");
if (dwFlags & AD_APPLY_SAVE) { // Don't ever modify the safemode settings
TCHAR szDeskcomp[MAX_PATH]; GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_GENERAL, _pszScheme); if (!StrStr(szDeskcomp, REG_DESKCOMP_SAFEMODE_SUFFIX)) { //
// Write out registry settings.
//
_SaveWallpaper(); _SaveComponents(); _SavePattern(SAVE_PATTERN_NAME); } };
if (dwFlags & AD_APPLY_HTMLGEN) { //We need to generate the Patten.bmp file too!
_SavePattern(GENERATE_PATTERN_FILE);
//
// Write out HTML file.
//
_GenerateHtml(); }
// The 3rd largest hang found by WindowsUpdate crash uploader has been that the Desktop hwnd hangs
// and the display CPYU
#define SENDMESSAGE_TIMEOUT (10 * 1000)
if (dwFlags & AD_APPLY_REFRESH) { HWND hwndShell = GetShellWindow(); SHELLSTATE ss = {0}; DWORD_PTR pdwTemp = 0;
SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); BOOL fWasActiveDesktop = BOOLIFY(ss.fDesktopHTML); BOOL fIsActiveDesktop = BOOLIFY(_co.fActiveDesktop);
if (fIsActiveDesktop && !IsICWCompleted()) TBOOL(DisableUndisplayableComponents(this)); if (fIsActiveDesktop != fWasActiveDesktop) { if (hwndShell) {
SendMessageTimeout(hwndShell, WM_WININICHANGE, SPI_SETDESKWALLPAPER, (LPARAM)TEXT("ToggleDesktop"), SMTO_NORMAL, SENDMESSAGE_TIMEOUT, &pdwTemp); }
//Force a SHRefresh with this dummy call
SHGetSetSettings(NULL, 0, TRUE); } else if (fIsActiveDesktop && hwndShell) { //See if we can simply make the changes dynamically instead of refreshing the whole page
// 98/09/22 #182982 vtan: Use dynamic HTML to refresh only if specifically told by a flag.
if (_fUseDynamicHtml && (dwFlags & AD_APPLY_DYNAMICREFRESH)) { SendMessageTimeout(hwndShell, DTM_MAKEHTMLCHANGES, (WPARAM)0, (LPARAM)0L, SMTO_NORMAL, SENDMESSAGE_TIMEOUT, &pdwTemp); } else { //Can't use dynamic html. We have to refresh the whole page.
SendMessageTimeout(hwndShell, WM_WININICHANGE, SPI_SETDESKWALLPAPER, (LPARAM)((dwFlags & AD_APPLY_BUFFERED_REFRESH) ? c_szBufferedRefresh : c_szRefreshDesktop), SMTO_NORMAL, SENDMESSAGE_TIMEOUT, &pdwTemp); } }
_fUseDynamicHtml = TRUE; }
//
// Data is no longer dirty.
//
_fDirty = FALSE; _fWallpaperDirty = FALSE; _fWallpaperChangedDuringInit = FALSE; _fPatternDirty = FALSE;
EXITPROC(2, "DS SaveSettings!"); }
ULONG CActiveDesktop::AddRef(void) { ENTERPROC(1, "DS AddRef()");
_cRef++;
EXITPROC(1, "DS AddRef=%d", _cRef); return _cRef; }
// pwzPath: The path where the temp files go (%userprofile%/windows)
// pszFile: The original file name ("Joe's Vacation Picture.jpg")
// pszInUse: The wallpaper in use.
HRESULT _DeleteUnusedTempFiles(IN LPCWSTR pwzPath, IN LPCTSTR pszFile) { TCHAR szTemplate[MAX_PATH]; WIN32_FIND_DATA findFileData; LPCTSTR pszFileName = PathFindFileName(pszFile);
HRESULT hr = StringCchPrintf(szTemplate, ARRAYSIZE(szTemplate), TEXT("%ls\\Wallpaper*.bmp"), pwzPath); if (SUCCEEDED(hr)) { HANDLE hFindFile = FindFirstFile(szTemplate, &findFileData);
if (INVALID_HANDLE_VALUE != hFindFile) { do { // Is this an old template? (Different name than we are currently using?
// Also, don't delete the wallpaper that is in use.
if (StrCmpI(findFileData.cFileName, pszFileName)) { DeleteFile(szTemplate); // Yes so delete it.
} } while (FindNextFile(hFindFile, &findFileData));
FindClose(hFindFile); } }
return hr; }
// nIndex: The file to try.
// pszInUse: This is the file we should skip because it's in use.
// pwzPath: On the way in, this is the selected wallpaper to convert.
// On the way out, this is is the converted file.
HRESULT _ConvertToTempFile(IN int nIndex, IN LPCWSTR pwzTempPath, IN LPTSTR pwzPath, IN int cchSize) { HRESULT hr = E_FAIL; WCHAR wzNewFile[MAX_PATH]; LPCWSTR pszFileName = PathFindFileName(pwzPath);
if (pszFileName) { hr = StringCchPrintf(wzNewFile, ARRAYSIZE(wzNewFile), L"%s\\Wallpaper%d.bmp", pwzTempPath, nIndex); if (SUCCEEDED(hr)) { hr = SHConvertGraphicsFile(pwzPath, wzNewFile, SHCGF_REPLACEFILE);
// This may fail for one of many reasons, and we just fall back to the old behavior if it fails.
// This may fail if they don't have write permission of the disk, run out of disk space, or
// this is a file type that we don't support.
if (SUCCEEDED(hr)) { hr = StringCchCopy(pwzPath, cchSize, wzNewFile); } } }
return hr; }
// pszFile: On the way in, this will contain the full path to the original file.
// On the way out, if we succeed, it will be modified to the temp file
// that is the converted equivalent of the file on the way in.
HRESULT CActiveDesktop::_ConvertFileToTempBitmap(IN LPWSTR pszFile, IN int cchSize) { HRESULT hr = E_FAIL; WCHAR wzPath[MAX_PATH];
if (S_OK == SHGetFolderPath(NULL, CSIDL_LOCAL_APPDATA, NULL, SHGFP_TYPE_CURRENT, wzPath) && PathAppend(wzPath, TEXT("Microsoft"))) { CreateDirectoryW(wzPath, NULL);
// Let's try the modified names to come up with something we can use.
for (int nIndex = 1; FAILED(hr) && (nIndex < 100); nIndex++) { hr = _ConvertToTempFile(nIndex, wzPath, pszFile, cchSize); }
if (SUCCEEDED(hr)) { _DeleteUnusedTempFiles(wzPath, pszFile); } }
return hr; }
#define SZ_REGKEY_CONTROLPANEL_DESKTOP TEXT("Control Panel\\Desktop")
#define SZ_REGVALUE_CONVERTED_WALLPAPER TEXT("ConvertedWallpaper")
#define SZ_REGVALUE_ORIGINAL_WALLPAPER TEXT("OriginalWallpaper") // We store this to find when someone changed the wallpaper around us
#define SZ_REGVALUE_WALLPAPER TEXT("Wallpaper")
#define SZ_REGVALUE_CONVERTED_WP_LASTWRITE TEXT("ConvertedWallpaper Last WriteTime")
HRESULT CActiveDesktop::_SaveTempWallpaperSettings(void) { HRESULT hr = E_FAIL;
// When we converted a non-.BMP wallpaper to a .bmp temp file,
// we keep the name of the original wallpaper path stored in _szSelectedWallpaper.
// We need to save that.
if (_szSelectedWallpaper) { hr = S_OK;
DWORD cbSize = sizeof(_szSelectedWallpaper[0]) * (lstrlen(_szSelectedWallpaper) + 1);
Str_SetPtr(&_pszOrigLastApplied, _szSelectedWallpaper);
// ISSUE: CONVERTED and ORIGINAL are backwards, but we shipped beta1 like this so we can't change it... blech
DWORD dwError = SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CONVERTED_WALLPAPER, REG_SZ, _szSelectedWallpaper, cbSize); hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr)) { Str_SetPtrW(&_pszWallpaperInUse, _szSelectedWallpaper); cbSize = sizeof(_szSelectedWallpaperConverted[0]) * (lstrlen(_szSelectedWallpaperConverted) + 1);
Str_SetPtr(&_pszOrigLastApplied, _szSelectedWallpaper);
dwError = SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_ORIGINAL_WALLPAPER, REG_SZ, (void *) _szSelectedWallpaperConverted, cbSize); hr = HRESULT_FROM_WIN32(dwError);
if (SUCCEEDED(hr)) { dwError = SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_WALLPAPER, REG_SZ, (void *) _szSelectedWallpaperConverted, cbSize); hr = HRESULT_FROM_WIN32(dwError); }
// Set date/time stamp of the original file (_szSelectedWallpaper) so we can later determine if the user changed the original.
if (_szSelectedWallpaper[0]) { HANDLE hFile = CreateFile(_szSelectedWallpaper, GENERIC_READ, (FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE), NULL, OPEN_EXISTING, 0, NULL);
if (INVALID_HANDLE_VALUE != hFile) { if (GetFileTime(hFile, NULL, NULL, &_ftLastWrite)) { dwError = SHSetValue(HKEY_CURRENT_USER, SZ_REGKEY_CONTROLPANEL_DESKTOP, SZ_REGVALUE_CONVERTED_WP_LASTWRITE, REG_BINARY, &_ftLastWrite, sizeof(_ftLastWrite)); hr = HRESULT_FROM_WIN32(dwError); }
CloseHandle(hFile); } } else { ULARGE_INTEGER * puli = (ULARGE_INTEGER *) &_ftLastWrite; puli->QuadPart = 0; } } }
return hr; }
HRESULT CActiveDesktop::ApplyChanges(DWORD dwFlags) { HRESULT hres = S_OK; ENTERPROC(1, "DS Apply(dwFlags=%08X)", dwFlags);
BOOL fActiveDesktop = FALSE; // default to disable active desktop
// determine if we should enable active desktop
if (SHRestricted(REST_FORCEACTIVEDESKTOPON)) { // if policy requires active desktop, then use that
fActiveDesktop = TRUE; } else { // if desktop components are locked -> active desktop is on
DWORD dwDesktopFlags = GetDesktopFlags(); if (dwDesktopFlags & COMPONENTS_LOCKED) { fActiveDesktop = TRUE; } else { // if desktop icons are hidden -> active desktop is on
SHELLSTATE ss; SHGetSetSettings(&ss, SSF_HIDEICONS, FALSE); if (ss.fHideIcons) { fActiveDesktop = TRUE; } } }
// Convert the background if needed.
// if background is not a .bmp --> active desktop is on if we can't auto-convert
if (!IsNormalWallpaper(_szSelectedWallpaper)) { BOOL fBitmapWallpaper = FALSE; // create the factory
IShellImageDataFactory* pImgFact; hres = CoCreateInstance(CLSID_ShellImageDataFactory, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellImageDataFactory, &pImgFact)); if (SUCCEEDED(hres)) { IShellImageData * pImage;
hres = pImgFact->CreateImageFromFile(_szSelectedWallpaper, &pImage); if (SUCCEEDED(hres)) { // PERF: cache decoded data
hres = pImage->Decode(SHIMGDEC_DEFAULT, 0, 0); if (SUCCEEDED(hres)) { if (S_FALSE == pImage->IsTransparent() && S_FALSE == pImage->IsAnimated()) { hres = StringCchCopy(_szSelectedWallpaperConverted, ARRAYSIZE(_szSelectedWallpaperConverted), _szSelectedWallpaper); if (SUCCEEDED(hres)) { HRESULT hrConvert = _ConvertFileToTempBitmap(_szSelectedWallpaperConverted, ARRAYSIZE(_szSelectedWallpaperConverted)); if (SUCCEEDED(hrConvert)) { if (S_OK == hrConvert) // if we actually had to convert (we may have already done the conversion)
{ _fDirty = TRUE; // if we converted, then we have changed the background and must persist it
_SaveTempWallpaperSettings(); hres = StringCchCopy(_szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper), _szSelectedWallpaperConverted); } fBitmapWallpaper = TRUE; } } } } pImage->Release(); } pImgFact->Release(); }
if (!fBitmapWallpaper) { fActiveDesktop = TRUE; } }
if (!fActiveDesktop) { // if any elements are checked --> active desktop is on
if (_hdsaComponent) { INT cComponents = DSA_GetItemCount(_hdsaComponent); for (INT i = 0; i < cComponents; i++) { COMPONENTA* pComponent = (COMPONENTA*)DSA_GetItemPtr(_hdsaComponent, i); if (pComponent && pComponent->fChecked) { fActiveDesktop = TRUE; break; } } } }
if (_co.fActiveDesktop != fActiveDesktop) { _co.fActiveDesktop = fActiveDesktop; _fDirty = TRUE; }
if (dwFlags & AD_APPLY_FORCE) { _fDirty = TRUE; _fWallpaperDirty = TRUE; _fPatternDirty = TRUE; }
if (_fDirty || _fWallpaperChangedDuringInit) { _SaveSettings(dwFlags); }
EXITPROC(1, "DS ApplyChanges=%d", hres);
return S_OK; }
ULONG CActiveDesktop::Release(void) { UINT nRet = --_cRef; ENTERPROC(1, "DS Release()");
if (_cRef == 0) { delete this; }
EXITPROC(1, "DS Release=%d", nRet); return nRet; }
CActiveDesktop::CActiveDesktop() { _cRef = 1; _fNoDeskMovr = FALSE; _fBackgroundHtml = FALSE; _fUseDynamicHtml = TRUE; _hdsaComponent = NULL; _pszScheme = NULL;
DllAddRef(); }
CActiveDesktop::~CActiveDesktop() { if (_hdsaComponent) { DSA_Destroy(_hdsaComponent); } if (_pszScheme) { LocalFree((HANDLE)_pszScheme); }
DllRelease(); }
HRESULT CActiveDesktop::GetWallpaper(LPWSTR pwszWallpaper, UINT cchWallpaper, DWORD dwReserved) { HRESULT hres = E_INVALIDARG; ENTERPROC(1, "DS GetWallpaper(pszWallpaper=%08X,cchWallpaper=%d)", pwszWallpaper, cchWallpaper);
ASSERT(!dwReserved); // These should be 0
if (pwszWallpaper && cchWallpaper) { hres = StringCchCopy(pwszWallpaper, cchWallpaper, _szSelectedWallpaper); if (SUCCEEDED(hres)) { if ( cchWallpaper < wcslen(_szSelectedWallpaper) ) { hres = MAKE_HRESULT( 0, FACILITY_WIN32, ERROR_MORE_DATA ); } else { hres = S_OK; } } } if (FAILED(hres)) { TraceMsg(TF_WARNING, "DS GetWallpaper unable to return wallpaper"); }
EXITPROC(1, "DS GetWallpaper=%d", hres); return hres; }
HRESULT CActiveDesktop::SetWallpaper(LPCWSTR pwszWallpaper, DWORD dwReserved) { HRESULT hres = E_INVALIDARG; WCHAR szTemp[MAX_PATH];
ASSERT(!dwReserved); // These should be 0
if (_fPolicyForWPName) // If a policy exists, the caller can not change the wallpaper.
return S_FALSE; if (pwszWallpaper) { hres = StringCchCopy(szTemp, ARRAYSIZE(szTemp), pwszWallpaper); if (SUCCEEDED(hres)) { hres = PathExpandEnvStringsWrap(szTemp, ARRAYSIZE(szTemp)); // We unexpand only when we persist.
if (SUCCEEDED(hres)) { if (lstrcmp(_szSelectedWallpaper, szTemp) != 0) { hres = StringCchCopy(_szSelectedWallpaper, ARRAYSIZE(_szSelectedWallpaper), szTemp); if (SUCCEEDED(hres)) { _fWallpaperDirty = TRUE; _fDirty = TRUE; _fUseDynamicHtml = FALSE; //Setting wallpaper causes a lot of change; So, can't use dynamic html
} } } } } ENTERPROC(1, "DS SetWallpaper(pszWallpaper=>%s<)", pwszWallpaper ? szTemp : TEXT("(NULL)"));
EXITPROC(1, "DS SetWallpaper=%d", hres); return hres; }
HRESULT CActiveDesktop::GetWallpaperOptions(WALLPAPEROPT *pwpo, DWORD dwReserved) { HRESULT hres = E_INVALIDARG; ENTERPROC(1, "DS GetWallpaperOptions(pwpo=%08X)");
ASSERT(!dwReserved); // These should be 0
if ((pwpo) && (pwpo->dwSize == sizeof(*pwpo))) { *pwpo = _wpo; hres = S_OK; } else { TraceMsg(TF_WARNING, "DS GetWallpaperOptions could not return options"); }
EXITPROC(1, "DS GetWallpaperOptions=%d", hres); return hres; }
HRESULT CActiveDesktop::SetWallpaperOptions(LPCWALLPAPEROPT pwpo, DWORD dwReserved) { HRESULT hres = E_INVALIDARG; ENTERPROC(1, "DS SetWallpaperOptions(pwpo=%08X)", pwpo);
ASSERT(!dwReserved); // These should be 0
if (_fPolicyForWPStyle) //If a policy exists for wallpaper style, the caller can not change it.
return S_FALSE;
if ((pwpo) && (pwpo->dwSize == sizeof(*pwpo))) { _wpo = *pwpo; _fWallpaperDirty = TRUE; _fDirty = TRUE; _fUseDynamicHtml = FALSE; //Changing wallpaper options causes us to regenerate the whole thing.
hres = S_OK; } else { TraceMsg(TF_WARNING, "DS SetWallpaperOptions could not set options"); }
EXITPROC(1, "DS SetWallpaperOptions=%d", hres); return hres; }
HRESULT CActiveDesktop::GetPattern(LPWSTR pwszPattern, UINT cchPattern, DWORD dwReserved) { HRESULT hres; ENTERPROC(1, "DS GetPattern(psz=%08X,cch=%d)", pwszPattern, cchPattern);
ASSERT(!dwReserved); // These should be 0
if (!pwszPattern || (cchPattern == 0)) { hres = E_INVALIDARG; } else { hres = StringCchCopy(pwszPattern, cchPattern, _szSelectedPattern); }
EXITPROC(1, "DS GetPattern=%d", hres); return hres; }
HRESULT CActiveDesktop::SetPattern(LPCWSTR pwszPattern, DWORD dwReserved) { ENTERPROC(1, "DS SetPattern(psz=>%s<)", pwszPattern ? pwszPattern : TEXT("(NULL)"));
HRESULT hres = E_INVALIDARG;
ASSERT(!dwReserved); // These should be 0
if (pwszPattern) { if (lstrcmp(_szSelectedPattern, pwszPattern) != 0) { hres = StringCchCopy(_szSelectedPattern, ARRAYSIZE(_szSelectedPattern), pwszPattern); if (SUCCEEDED(hres)) { _fPatternDirty = TRUE; _fDirty = TRUE; _fUseDynamicHtml = FALSE; //Setting pattern causes us to regenerate the whole thing.
} } else { hres = E_FAIL; } }
EXITPROC(1, "DS SetPattern=%d", hres); return hres; }
HRESULT CActiveDesktop::GetDesktopItemOptions(COMPONENTSOPT *pco, DWORD dwReserved) { HRESULT hres = E_INVALIDARG; ENTERPROC(1, "DS GetComponentsOptions(pco=%08X)", pco);
ASSERT(!dwReserved); // These should be 0
if (pco && (pco->dwSize == sizeof(*pco))) { *pco = _co; hres = S_OK; } else { TraceMsg(TF_WARNING, "DS GetComponentsOptions unable to return options"); }
EXITPROC(1, "DS GetComponentsOptions=%d", hres); return hres; }
HRESULT CActiveDesktop::SetDesktopItemOptions(LPCCOMPONENTSOPT pco, DWORD dwReserved) { HRESULT hres = E_INVALIDARG; ENTERPROC(1, "DS SetComponentsOptions(pco=%08X)", pco);
ASSERT(!dwReserved); // These should be 0
if (pco && (pco->dwSize == sizeof(*pco))) { _co = *pco; _fDirty = TRUE; hres = S_OK; } else { TraceMsg(TF_WARNING, "DS SetComponentsOptions unable to set options"); }
EXITPROC(1, "DS SetComponentsOptions=%d", hres); return hres; }
//
// SetStateInfo()
// This function simply sets up the COMPSTATEINFO structure passed using the current
// position and size from the COMPPOS structure and the itemState passed.
//
void SetStateInfo(COMPSTATEINFO *pCompStateInfo, COMPPOS *pCompPos, DWORD dwItemState) { pCompStateInfo->dwSize = sizeof(*pCompStateInfo); pCompStateInfo->iLeft = pCompPos->iLeft; pCompStateInfo->iTop = pCompPos->iTop; pCompStateInfo->dwWidth = pCompPos->dwWidth; pCompStateInfo->dwHeight = pCompPos->dwHeight; pCompStateInfo->dwItemState = dwItemState; }
void ConvertCompStruct(COMPONENTA *pCompDest, COMPONENTA *pCompSrc, BOOL fPubToPriv) { pCompDest -> dwID = pCompSrc -> dwID; pCompDest -> iComponentType = pCompSrc -> iComponentType; pCompDest -> fChecked = pCompSrc -> fChecked; pCompDest -> fDirty = pCompSrc -> fDirty; pCompDest -> fNoScroll = pCompSrc -> fNoScroll; pCompDest -> cpPos = pCompSrc -> cpPos;
if (fPubToPriv) { COMPONENT *pComp = (COMPONENT *)pCompSrc;
pCompDest->dwSize = sizeof(COMPONENTA); SHUnicodeToTChar(pComp->wszSource, pCompDest->szSource, ARRAYSIZE(pCompDest->szSource)); SHUnicodeToTChar(pComp->wszFriendlyName, pCompDest->szFriendlyName, ARRAYSIZE(pCompDest->szFriendlyName)); SHUnicodeToTChar(pComp->wszSubscribedURL, pCompDest->szSubscribedURL, ARRAYSIZE(pCompDest->szSubscribedURL)); //Check to see if the public component is from IE4 app (old size)
if (pCompSrc->dwSize == sizeof(COMPONENT)) { // Since the dest component is the same size as the most current structure, all fields
// are valid.
// CAUTION: The following fields are at a different offset in public and private
// structures. So, you need to use pcomp instead of pCompSrc for example.
pCompDest->dwCurItemState = pComp->dwCurItemState; pCompDest->csiOriginal = pComp->csiOriginal; pCompDest->csiRestored = pComp->csiRestored; } else { // Since the size did not match, we assume that this is an older structure.
// Since the older struct does not have any Original and Restored sizes, let's copy
// the default values.
IE4COMPONENT *pIE4Comp = (IE4COMPONENT *)pCompSrc; pCompDest->dwCurItemState = IS_NORMAL; SetStateInfo(&pCompDest->csiOriginal, &pIE4Comp->cpPos, IS_NORMAL); SetStateInfo(&pCompDest->csiRestored, &pIE4Comp->cpPos, IS_NORMAL); } } else { COMPONENT *pComp = (COMPONENT *)pCompDest; if (pCompDest->dwSize != sizeof(COMPONENT)) pCompDest->dwSize = sizeof(IE4COMPONENT); SHTCharToUnicode(pCompSrc->szSource, pComp->wszSource, ARRAYSIZE(pComp->wszSource)); SHTCharToUnicode(pCompSrc->szFriendlyName, pComp->wszFriendlyName, ARRAYSIZE(pComp->wszFriendlyName)); SHTCharToUnicode(pCompSrc->szSubscribedURL, pComp->wszSubscribedURL, ARRAYSIZE(pComp->wszSubscribedURL)); //Check to see if the public component is from IE4 app (old size)
if (pComp->dwSize == sizeof(COMPONENT)) { // Since the dest component is the same size as the most current structure, all fields
// are valid.
// CAUTION: The following fields are at a different offset in public and private
// structures. So, you need to use pcomp instead of pCompDest for example.
pComp->dwCurItemState = pCompSrc->dwCurItemState; pComp->csiOriginal = pCompSrc->csiOriginal; pComp->csiRestored = pCompSrc->csiRestored; } // else, the dest component is IE4COMPONENT and the additional fields are not there.
} }
HRESULT CActiveDesktop::_AddDTIWithUIPrivateA(HWND hwnd, LPCCOMPONENT pComp, DWORD dwFlags) { HRESULT hres = E_FAIL; PCWSTR pszUrl = pComp->wszSource; int nScheme = GetUrlScheme(pszUrl); DWORD dwCurItemState; if ((URL_SCHEME_INVALID == nScheme) || (URL_SCHEME_UNKNOWN == nScheme)) { TCHAR szFullyQualified[INTERNET_MAX_URL_LENGTH]; DWORD cchSize = ARRAYSIZE(szFullyQualified);
if (SUCCEEDED(ParseURLFromOutsideSource(pszUrl, szFullyQualified, &cchSize, NULL))) nScheme = GetUrlScheme(szFullyQualified); }
// Is this URL valid to subscribe to? Did the caller specify they want use
// to try to subscribe to it?
if ((URL_SCHEME_FILE != nScheme) && (URL_SCHEME_ABOUT != nScheme) && IsFlagSet(dwFlags, DTI_ADDUI_DISPSUBWIZARD) && hwnd) { //Create a subscription.
hres = CreateSubscriptionsWizard(SUBSTYPE_DESKTOPURL, pszUrl, NULL, hwnd); if (hres != S_OK) { return hres; } }
//
// Add the component to the registry.
//
// PERF: This function creates a second COM objects.
// We need to Inline the functionality.
if (pComp->dwSize == sizeof(IE4COMPONENT)) dwCurItemState = IS_NORMAL; else dwCurItemState = pComp->dwCurItemState; hres = AddRemoveDesktopComponentNoUI(TRUE, AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH, pszUrl, NULL, pComp->iComponentType, pComp->cpPos.iLeft, pComp->cpPos.iTop, pComp->cpPos.dwWidth, pComp->cpPos.dwHeight, TRUE, dwCurItemState) ? S_OK : E_FAIL;
return hres; }
#define STC_DESKTOPCOMPONENT 0x00000002
STDAPI SubscribeToCDF(HWND hwndParent, LPCWSTR pwzUrl, DWORD dwCDFTypes);
HRESULT CActiveDesktop::AddDesktopItemWithUI(HWND hwnd, LPCOMPONENT pComp, DWORD dwFlags) { HRESULT hres = E_FAIL;
// We need to support IE4 apps calling with the old component structure too!
// We use the size field to detect IE4 v/s newer apps!
if (!pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT))) || ((pComp->dwSize == sizeof(*pComp)) && !VALIDATESTATE(pComp->dwCurItemState)) || ((pComp->iComponentType < 0) || (pComp->iComponentType > COMP_TYPE_MAX))) //Validate the component type
return E_INVALIDARG;
// Catch folks that call our API's to add components and prevent them from doing
// so if the restriction is in place.
if (SHIsRestricted(NULL, REST_NOADDDESKCOMP)) return E_ACCESSDENIED;
// Check if the component already exists.
BOOL fCompExists = FALSE; int cComp; GetDesktopItemCount(&cComp, 0); int i; COMPONENT comp; comp.dwSize = sizeof(COMPONENT); //This needs to be initialized for ConvertCompStruc to work!
COMPONENTA compA; TCHAR szSource[INTERNET_MAX_URL_LENGTH]; SHUnicodeToTChar(pComp->wszSource, szSource, ARRAYSIZE(szSource));
for (i=0; i<cComp && !fCompExists; i++) { compA.dwSize = sizeof(compA); if (GetComponentPrivate(i, &compA) && lstrcmpi(szSource, compA.szSource) == 0) { fCompExists = TRUE; ConvertCompStruct((COMPONENTA *)&comp, &compA, FALSE); break; } }
BOOL fAskToInstall; if (ZoneCheckUrlW(pComp->wszSource, URLACTION_SHELL_INSTALL_DTITEMS, (PUAF_NOUI), NULL) == S_OK) { fAskToInstall = TRUE; } else { fAskToInstall = FALSE; }
if (S_OK != ZoneCheckUrlW(pComp->wszSource, URLACTION_SHELL_INSTALL_DTITEMS, (hwnd ? (PUAF_FORCEUI_FOREGROUND | PUAF_WARN_IF_DENIED) : PUAF_NOUI), NULL)) return E_ACCESSDENIED;
BOOL fCompSubDeleted = FALSE; SUBSCRIPTIONINFO si = {sizeof(SUBSCRIPTIONINFO)}; // si.bstrUserName = NULL;
// si.bstrPassword = NULL;
// si.bstrFriendlyName = NULL;
//
// Confirmation dialog.
//
if (hwnd) { if (fCompExists) { //Prompt the user to delete the existing ADI.
// This is a long string. So,...
TCHAR szMsg[512]; TCHAR szMsg2[256]; TCHAR szTitle[128]; LoadString(HINST_THISDLL, IDS_COMP_EXISTS, szMsg, ARRAYSIZE(szMsg)); LoadString(HINST_THISDLL, IDS_COMP_EXISTS_2, szMsg2, ARRAYSIZE(szMsg2)); StringCchCat(szMsg, ARRAYSIZE(szMsg), szMsg2); // truncation is fine, this is display text
LoadString(HINST_THISDLL, IDS_COMP_TITLE, szTitle, ARRAYSIZE(szTitle)); MessageBox(hwnd, szMsg, szTitle, MB_OK);
return E_FAIL; } else if (fAskToInstall) { if (ShellMessageBox(HINST_THISDLL, hwnd, MAKEINTRESOURCE(IDS_CONFIRM_ADD), MAKEINTRESOURCE(IDS_INTERNET_EXPLORER), MB_YESNO) != IDYES) { return E_FAIL; //User choses not to install this desktop component!
} } }
hres = SubscribeToCDF(hwnd, pComp->wszSubscribedURL, STC_DESKTOPCOMPONENT); switch(hres) { case E_INVALIDARG: { // E_UNEXPECTED is returned from SubscribeToCDFUrlA() when the URL doesn't point to
// a CDF file, so we assume it's a web page.
hres = _AddDTIWithUIPrivateA(hwnd, pComp, dwFlags); if (hres != S_OK && fCompSubDeleted) // Restore the old component
{ hres = AddDesktopItem(&comp, 0); if (SUCCEEDED(hres)) { ISubscriptionMgr *psm; if (SUCCEEDED(CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void**)&psm))) { si.cbSize = sizeof(si); psm->CreateSubscription(hwnd, comp.wszSubscribedURL, si.bstrFriendlyName, CREATESUBS_NOUI, SUBSTYPE_DESKTOPURL, &si); psm->Release(); } else { TraceMsg(TF_WARNING, "CActiveDesktop::AddDesktopItemWithUI : CoCreateInstance for CLSID_SubscriptionMgr failed."); } } } ApplyChanges(AD_APPLY_ALL | AD_APPLY_DYNAMICREFRESH); } break;
case E_ACCESSDENIED: // The file was a CDF but didn't contain Desktop Component Information
if (hwnd) { TCHAR szMsg[MAX_PATH]; TCHAR szTitle[MAX_PATH];
LoadString(HINST_THISDLL, IDS_ADDCOMP_ERROR_CDFNODTI, szMsg, ARRAYSIZE(szMsg)); LoadString(HINST_THISDLL, IDS_INTERNET_EXPLORER, szTitle, ARRAYSIZE(szTitle)); MessageBox(hwnd, szMsg, szTitle, MB_OK); } break; case E_UNEXPECTED: // This was a CDF but it was misauthored.
if (hwnd) { TCHAR szMsg[MAX_PATH]; TCHAR szTitle[MAX_PATH];
LoadString(HINST_THISDLL, IDS_ADDCOMP_ERROR_CDFINALID, szMsg, ARRAYSIZE(szMsg)); LoadString(HINST_THISDLL, IDS_INTERNET_EXPLORER, szTitle, ARRAYSIZE(szTitle)); MessageBox(hwnd, szMsg, szTitle, MB_OK); } break; default: break; }
if (hwnd && SUCCEEDED(hres)) { // If the active desktop is currently OFF, we need to turn it ON
SHELLSTATE ss = {0}; SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); if (!ss.fDesktopHTML) { COMPONENTSOPT co; co.dwSize = sizeof(COMPONENTSOPT); GetDesktopItemOptions(&co, 0); co.fActiveDesktop = TRUE; SetDesktopItemOptions(&co, 0); ApplyChanges(AD_APPLY_REFRESH | AD_APPLY_DYNAMICREFRESH); } }
if (fCompSubDeleted) { if (si.bstrUserName) { SysFreeString(si.bstrUserName); } if (si.bstrPassword) { SysFreeString(si.bstrPassword); } if (si.bstrFriendlyName) { SysFreeString(si.bstrFriendlyName); } } return hres; }
void RestoreComponent(HDSA hdsaComponents, COMPONENTA * pcomp) { int i;
// If we are split then set the bit saying that the listview needs to be adjusted. This is done
// when we check the state of desktop.htm in EnsureUpdateHtml.
// Note: Do this only if this component is enabled.
if ((pcomp->dwCurItemState & IS_SPLIT) && (pcomp->fChecked)) { pcomp->dwCurItemState |= IS_ADJUSTLISTVIEW; SetDesktopFlags(COMPONENTS_ZOOMDIRTY, COMPONENTS_ZOOMDIRTY); }
for (i = 0; i < DSA_GetItemCount(hdsaComponents); i++) { COMPONENTA * pcompT; if (pcompT = (COMPONENTA *)DSA_GetItemPtr(hdsaComponents, i)) { // If this component is split/fullscreen and is different from the source component
// but it is at the same location then it must be on this monitor (work area) so restore it.
if (ISZOOMED(pcompT) && lstrcmpi(pcomp->szSource, pcompT->szSource) && (pcomp->cpPos.iTop == pcompT->cpPos.iTop) && ((pcomp->cpPos.iLeft + pcomp->cpPos.dwWidth) == (pcompT->cpPos.iLeft + pcompT->cpPos.dwWidth))) { pcompT->dwCurItemState = pcompT->csiRestored.dwItemState; pcompT->cpPos.iLeft = pcompT->csiRestored.iLeft; pcompT->cpPos.iTop = pcompT->csiRestored.iTop; pcompT->cpPos.dwWidth = pcompT->csiRestored.dwWidth; pcompT->cpPos.dwHeight = pcompT->csiRestored.dwHeight; pcompT->cpPos.izIndex = COMPONENT_TOP; pcompT->fDirty = TRUE; break; } } } }
HRESULT CActiveDesktop::AddDesktopItem(LPCCOMPONENT pComp, DWORD dwReserved) { HRESULT hres = E_FAIL; COMPONENTA CompA; CompA.dwSize = sizeof(CompA);
ASSERT(!dwReserved); // These should be 0
// We need to support IE4 apps calling with the old component structure too!
// We use the size field to detect IE4 v/s newer apps!
if (!pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT))) || ((pComp->dwSize == sizeof(*pComp)) && !VALIDATESTATE(pComp->dwCurItemState))) return E_INVALIDARG;
// Catch folks that call our API's to add components and prevent them from doing
// so if the restriction is in place.
if ((!_fIgnoreAddRemovePolicies) && (SHIsRestricted(NULL, REST_NOADDDESKCOMP))) return E_ACCESSDENIED;
// Convert the external structure to the internal format
ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE); // If the component is already present, then fail the call!
if (_FindComponentBySource(CompA.szSource, &CompA) > -1) return hres;
//Make sure that the COMPPOS size field is set before we add it!
CompA.cpPos.dwSize = sizeof(COMPPOS);
PositionComponent(&CompA, &CompA.cpPos, CompA.iComponentType, TRUE);
if (_hdsaComponent && ISZOOMED(&CompA)) RestoreComponent(_hdsaComponent, &CompA);
//Make sure the this component's fDirty flag is off.
CompA.fDirty = FALSE;
// Set the dummy bit here - this forces folks to do bitwise testing on the dwCurItemState field
// instead of testing for equality. This will allow us to expand use of the field down the
// road without compatibility problems.
CompA.dwCurItemState |= IS_INTERNALDUMMYBIT;
if (AddComponentPrivate(&CompA, _dwNextID++)) { // It might be cheaper to attempt to insert the component in the
// correct z-order but it's less code to just call _SortAndRationalize
// after the insertion is done.
_SortAndRationalize(); hres = S_OK; }
return(hres); }
BOOL CActiveDesktop::AddComponentPrivate(COMPONENTA *pcomp, DWORD dwID) { BOOL fRet = FALSE; ENTERPROC(1, "DS AddComponent(pcomp=%08X)", pcomp);
if (pcomp) { if (_hdsaComponent == NULL) { _hdsaComponent = DSA_Create(sizeof(COMPONENTA), DXA_GROWTH_CONST); }
if (_hdsaComponent) { pcomp->dwID = dwID;
if (DSA_AppendItem(_hdsaComponent, pcomp) != -1) { _fDirty = TRUE; fRet = TRUE; } else { TraceMsg(TF_WARNING, "DS AddComponent unable to append DSA"); } } else { TraceMsg(TF_WARNING, "DS AddComponent unable to create DSA"); } } else { TraceMsg(TF_WARNING, "DS AddComponent unable to add a component"); }
EXITPROC(1, "DS AddComponent=%d", fRet); return fRet; }
//
// This finds out if a given component already exists by comparing the szSource
// If so, it fills out the correct dwID and returns the index.
//
int CActiveDesktop::_FindComponentBySource(LPTSTR lpszSource, COMPONENTA *pComp) { int iRet = -1; ENTERPROC(2, "DS FindComponentIdBySource(pComp=%8X)", pComp);
if (_hdsaComponent) { int i;
for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++) { COMPONENTA comp; comp.dwSize = sizeof(COMPONENTA);
if (DSA_GetItem(_hdsaComponent, i, &comp) != -1) { if (!lstrcmpi(comp.szSource, lpszSource)) { *pComp = comp; iRet = i; break; } } else { TraceMsg(TF_WARNING, "DS FindComponentIndexByID unable to get a component"); } } }
EXITPROC(2, "DS FindComponentIdBySource=%d", iRet); return iRet; }
int CActiveDesktop::_FindComponentIndexByID(DWORD dwID) { int iRet = -1; ENTERPROC(2, "DS FindComponentIndexByID(dwID=%d)", dwID);
if (_hdsaComponent) { int i;
for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++) { COMPONENTA comp; comp.dwSize = sizeof(COMPONENTA);
if (DSA_GetItem(_hdsaComponent, i, &comp) != -1) { if (comp.dwID == dwID) { iRet = i; break; } } else { TraceMsg(TF_WARNING, "DS FindComponentIndexByID unable to get a component"); } } }
EXITPROC(2, "DS FindComponent=%d", iRet); return iRet; }
//
// This function is to be used only in special situations. Given a Url, it finds a component
// that has the src= pointed to that url. Note that what we have is szSource is something like
// "c:\foo\bar.bmp"; But, what is passed to this function is "file://c:/foo/bar.htm"
//
// Warning: This function does a conversion from Path to Url for every component before
// comparing with the given Url. This is in-efficient. We do it this way because converting
// the given Url ,which was converted to url from path, back to Path may not result in the
// original path. In other words a round-trip from path to Url and back to path may not result
// in the path that was originally entered by the end-user.
//
int CActiveDesktop::_FindComponentBySrcUrl(LPTSTR lpszSrcUrl, COMPONENTA *pComp) { int iRet = -1; ENTERPROC(2, "DS FindComponentBySrcUrl(pComp=%8X)", pComp);
if (_hdsaComponent) { int i;
for (i=0; i<DSA_GetItemCount(_hdsaComponent); i++) { COMPONENTA comp; comp.dwSize = sizeof(COMPONENTA);
if (DSA_GetItem(_hdsaComponent, i, &comp) != -1) { TCHAR szUrl[INTERNET_MAX_URL_LENGTH]; LPTSTR lpszUrl = szUrl; DWORD dwSize;
//Convert the szSource to Url
dwSize = ARRAYSIZE(szUrl); if (FAILED(UrlCreateFromPath(comp.szSource, lpszUrl, &dwSize, 0))) lpszUrl = comp.szSource; if (!lstrcmpi(lpszUrl, lpszSrcUrl)) { *pComp = comp; iRet = i; break; } } else { TraceMsg(TF_WARNING, "DS FindComponentBySrcUrl unable to get a component"); } } }
EXITPROC(2, "DS FindComponentBySrcUrl=%d", iRet); return iRet; }
HRESULT CActiveDesktop:: GetDesktopItemByID(ULONG_PTR dwID, COMPONENT *pcomp, DWORD dwReserved) { HRESULT hres = E_FAIL; ENTERPROC(1, "DS GetComponentByID(dwID=%d,pcomp=%08X)", dwID, pcomp); COMPONENTA CompA;
ASSERT(!dwReserved); // These should be 0
// We need to support IE4 apps calling with the old component structure too!
// We use the size field to detect IE4 v/s newer apps!
if (!pcomp || ((pcomp->dwSize != sizeof(*pcomp)) && (pcomp->dwSize != sizeof(IE4COMPONENT)))) return E_INVALIDARG;
if (pcomp) { int index = _FindComponentIndexByID((DWORD)dwID); if (index != -1) { if (DSA_GetItem(_hdsaComponent, index, &CompA) != -1) { hres = S_OK; } else { TraceMsg(TF_WARNING, "DS GetComponentByID unable to get component"); } } else { TraceMsg(TF_WARNING, "DS GetComponentByID unable to find component"); } } else { TraceMsg(TF_WARNING, "DS GetComponentByID given NULL pcomp"); }
if (SUCCEEDED(hres)) { MultiCompToWideComp(&CompA, pcomp); }
EXITPROC(1, "DS GetComponentByID=%d", hres); return hres; }
HRESULT CActiveDesktop::RemoveDesktopItem(LPCCOMPONENT pComp, DWORD dwReserved) { COMPONENTA CompA, CompToDelete; int iIndex; HRESULT hres = E_FAIL;
ASSERT(!dwReserved); // These should be 0
// We need to support IE4 apps calling with the old component structure too!
// We use the size field to detect IE4 v/s newer apps!
if (!pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT)))) return E_INVALIDARG;
CompA.dwSize = sizeof(CompA); CompToDelete.dwSize = sizeof(CompToDelete);
//Convert the struct to internal struct.
ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE);
// See if the component already exists.
iIndex = _FindComponentBySource(CompA.szSource, &CompToDelete);
if (iIndex > -1) { if (RemoveComponentPrivate(iIndex, &CompToDelete)) { hres = S_OK; } }
return(hres); }
BOOL CActiveDesktop::RemoveComponentPrivate(int iIndex, COMPONENTA *pcomp) { BOOL fRet = FALSE; ENTERPROC(1, "DS RemoveComponent(pcomp=%08X)", pcomp);
if (_hdsaComponent) { if (iIndex == -1) iIndex = _FindComponentIndexByID(pcomp->dwID); if (iIndex != -1) { if (DSA_DeleteItem(_hdsaComponent, iIndex) != -1) { _fDirty = TRUE; fRet = TRUE; } else { TraceMsg(TF_WARNING, "DS RemoveComponent could not remove an item"); } } else { TraceMsg(TF_WARNING, "DS RemoveComponent could not find item to remove"); } } else { TraceMsg(TF_WARNING, "DS RemoveComponent has no components to remove"); }
EXITPROC(1, "DS RemoveComponent=%d", fRet); return fRet; }
HRESULT CActiveDesktop::_CopyComponent(COMPONENTA *pCompDest, COMPONENTA *pCompSrc, DWORD dwFlags) { HRESULT hrTemp, hr = S_OK;
//Copy only those elements mentioned in the flag!
// if (dwFlags & COMP_ELEM_ID)
// pCompDest->dwID = pCompSrc->dwID;
if (dwFlags & COMP_ELEM_TYPE) pCompDest-> iComponentType = pCompSrc->iComponentType; if (dwFlags & COMP_ELEM_CHECKED) pCompDest-> fChecked = pCompSrc->fChecked; if (dwFlags & COMP_ELEM_DIRTY) pCompDest-> fDirty = pCompSrc-> fDirty; if (dwFlags & COMP_ELEM_NOSCROLL) pCompDest-> fNoScroll = pCompSrc-> fNoScroll; if (dwFlags & COMP_ELEM_POS_LEFT) pCompDest-> cpPos.iLeft= pCompSrc->cpPos.iLeft; if (dwFlags & COMP_ELEM_POS_TOP) pCompDest-> cpPos.iTop= pCompSrc->cpPos.iTop; if (dwFlags & COMP_ELEM_SIZE_WIDTH) pCompDest-> cpPos.dwWidth= pCompSrc->cpPos.dwWidth; if (dwFlags & COMP_ELEM_SIZE_HEIGHT) pCompDest-> cpPos.dwHeight= pCompSrc->cpPos.dwHeight; if (dwFlags & COMP_ELEM_POS_ZINDEX) pCompDest-> cpPos.izIndex= pCompSrc->cpPos.izIndex; if (dwFlags & COMP_ELEM_SOURCE) { hrTemp = StringCchCopy(pCompDest->szSource, ARRAYSIZE(pCompDest->szSource), pCompSrc->szSource); if (FAILED(hrTemp)) { hr = hrTemp; } } if (dwFlags & COMP_ELEM_FRIENDLYNAME) { hrTemp = StringCchCopy(pCompDest->szFriendlyName, ARRAYSIZE(pCompDest->szFriendlyName), pCompSrc->szFriendlyName); if (FAILED(hrTemp)) { hr = hrTemp; } }
if (dwFlags & COMP_ELEM_SUBSCRIBEDURL) { hrTemp = StringCchCopy(pCompDest->szSubscribedURL, ARRAYSIZE(pCompDest->szSubscribedURL), pCompSrc->szSubscribedURL); if (FAILED(hrTemp)) { hr = hrTemp; } } if (dwFlags & COMP_ELEM_ORIGINAL_CSI) pCompDest->csiOriginal = pCompSrc->csiOriginal; if (dwFlags & COMP_ELEM_RESTORED_CSI) { pCompDest->csiRestored = pCompSrc->csiRestored;
// 98/08/21 vtan #174542: When changing csiRestored using the Active
// Desktop API and the component is zoomed the csiRestored information
// needs to be copied to the cpPos field as well as this is where the
// actual information is stored when the component is restored. This
// is only applicable to the case when the component is zoomed.
if (ISZOOMED(pCompDest)) { pCompDest->cpPos.iLeft = pCompSrc->csiRestored.iLeft; pCompDest->cpPos.iTop = pCompSrc->csiRestored.iTop; pCompDest->cpPos.dwWidth = pCompSrc->csiRestored.dwWidth; pCompDest->cpPos.dwHeight = pCompSrc->csiRestored.dwHeight; } } if (dwFlags & COMP_ELEM_CURITEMSTATE) // Only allow the modification of the public bits - propagate the internal bits unchanged.
pCompDest->dwCurItemState = (pCompDest->dwCurItemState & IS_VALIDINTERNALBITS) | (pCompSrc->dwCurItemState & ~IS_VALIDINTERNALBITS);
return hr; }
HRESULT CActiveDesktop::GetDesktopItemBySource(LPCWSTR lpcwszSource, LPCOMPONENT pComp, DWORD dwFlags) { COMPONENTA CompNew; HRESULT hres = E_FAIL; int iIndex;
//Passing a NULL to SHUnicodeToTChar causes a fault. So, let's fail it.
if (lpcwszSource == NULL) return E_INVALIDARG; // We need to support IE4 apps calling with the old component structure too!
// We use the size field to detect IE4 v/s newer apps!
if (!pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT)))) return E_INVALIDARG;
CompNew.dwSize = sizeof(COMPONENTA);
SHUnicodeToTChar(lpcwszSource, CompNew.szSource, ARRAYSIZE(CompNew.szSource));
iIndex = _FindComponentBySource(CompNew.szSource, &CompNew);
if (iIndex > -1) { MultiCompToWideComp(&CompNew, pComp); hres = S_OK; }
return(hres); }
HRESULT CActiveDesktop::ModifyDesktopItem(LPCCOMPONENT pComp, DWORD dwFlags) { COMPONENTA CompA, CompNew; HRESULT hres = E_FAIL; int iIndex = -1;
// We need to support IE4 apps calling with the old component structure too!
// We use the size field to detect IE4 v/s newer apps!
if (!pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT)))) return E_INVALIDARG;
CompA.dwSize = sizeof(COMPONENTA); CompNew.dwSize = sizeof(COMPONENTA);
//Convert public param structure to private param structure.
ConvertCompStruct(&CompA, (COMPONENTA *)pComp, TRUE);
//See if this component already exists.
iIndex = _FindComponentBySource(CompA.szSource, &CompNew); if (iIndex > -1) { hres = _CopyComponent(&CompNew, &CompA, dwFlags); if (SUCCEEDED(hres)) { if (dwFlags & (COMP_ELEM_POS_LEFT | COMP_ELEM_POS_TOP | COMP_ELEM_SIZE_WIDTH | COMP_ELEM_SIZE_HEIGHT | COMP_ELEM_CHECKED | COMP_ELEM_CURITEMSTATE)) PositionComponent(&CompNew, &CompNew.cpPos, CompNew.iComponentType, FALSE); if (ISZOOMED(&CompNew)) RestoreComponent(_hdsaComponent, &CompNew);
CompNew.fDirty = TRUE; //Since the component is modified, we set the dirty bit!
if (UpdateComponentPrivate(iIndex, &CompNew)) hres = S_OK; } }
return(hres); }
BOOL CActiveDesktop::UpdateComponentPrivate(int iIndex, COMPONENTA *pcomp) { BOOL fRet = FALSE; ENTERPROC(1, "DS UpdateComponentPrivate(pcomp=%08X)", pcomp);
if (_hdsaComponent) { if (iIndex == -1) iIndex = _FindComponentIndexByID(pcomp->dwID);
if (iIndex != -1) { if (DSA_SetItem(_hdsaComponent, iIndex, pcomp) != -1) { _fDirty = TRUE; fRet = TRUE; } else { TraceMsg(TF_WARNING, "DS UpdateComponent could not update an item"); } } else { TraceMsg(TF_WARNING, "DS UpdateComponent could not find item to update"); } } else { TraceMsg(TF_WARNING, "DS UpdateComponent has no components to update"); }
EXITPROC(1, "DS UpdateComponent=%d", fRet); return fRet; }
HRESULT CActiveDesktop::GetDesktopItemCount(LPINT lpiCount, DWORD dwReserved) { if (!lpiCount) return (E_INVALIDARG);
*lpiCount = 0;
ENTERPROC(1, "DS GetComponentsCount()");
ASSERT(!dwReserved); // These should be 0
if (_hdsaComponent) { *lpiCount = DSA_GetItemCount(_hdsaComponent); }
EXITPROC(1, "DS GetComponentsCount=%d", *lpiCount); return S_OK; }
HRESULT CActiveDesktop::GetDesktopItem(int nComponent, COMPONENT *pComp, DWORD dwReserved) { COMPONENTA CompA;
ASSERT(!dwReserved); // These should be 0
// We need to support IE4 apps calling with the old component structure too!
// We use the size field to detect IE4 v/s newer apps!
if ((nComponent < 0) || !pComp || ((pComp->dwSize != sizeof(*pComp)) && (pComp->dwSize != sizeof(IE4COMPONENT)))) return E_INVALIDARG;
CompA.dwSize = sizeof(COMPONENTA);
if (GetComponentPrivate(nComponent, &CompA)) { //Convert the structure to the Public form.
ConvertCompStruct((COMPONENTA *)pComp, &CompA, FALSE); return(S_OK); } else return(E_FAIL); }
BOOL CActiveDesktop::GetComponentPrivate(int nComponent, COMPONENTA *pcomp) { BOOL fRet = FALSE; ENTERPROC(1, "DS GetComponent(nComponent=%d,pcomp=%08X)", nComponent, pcomp);
if (_hdsaComponent && pcomp && (nComponent < DSA_GetItemCount(_hdsaComponent))) { if (DSA_GetItem(_hdsaComponent, nComponent, pcomp) != -1) { fRet = TRUE; } else { TraceMsg(TF_WARNING, "DS GetComponent unable to get a component"); } } else { TraceMsg(TF_WARNING, "DS GetComponent does not have a DSA"); }
EXITPROC(1, "DS GetComponent=%d", fRet); return fRet; }
HRESULT CActiveDesktop::QueryInterface(REFIID riid, LPVOID *ppvObj) { if (IsEqualIID(riid, IID_IActiveDesktop)) { *ppvObj = (IActiveDesktop *)this; _Initialize(); } else if (IsEqualIID(riid, IID_IUnknown)) { *ppvObj = (IActiveDesktop *)this; } else if (IsEqualIID(riid, IID_IActiveDesktopP)) { *ppvObj = (IActiveDesktopP *)this; } else if (IsEqualIID(riid, IID_IADesktopP2)) { *ppvObj = (IADesktopP2 *)this; } else if (IsEqualIID(riid, IID_IPropertyBag)) { *ppvObj = (IPropertyBag *)this; } else { *ppvObj = NULL; return E_NOINTERFACE; }
AddRef(); return S_OK; }
// Helper function so that it's easy to create one internally
// Actually, it's not ver much help any more...
STDAPI CActiveDesktop_InternalCreateInstance(LPUNKNOWN * ppunk, REFIID riid) { return CActiveDesktop_CreateInstance(NULL, riid, (void **)ppunk); }
// Our class factory create instance code
STDAPI CActiveDesktop_CreateInstance(LPUNKNOWN punkOuter, REFIID riid, void **ppvOut) { TraceMsg(TF_DESKSTAT, "CActiveDesktop- CreateInstance");
CActiveDesktop *pad = new CActiveDesktop();
if (pad) { HRESULT hres = pad->QueryInterface(riid, ppvOut); pad->Release(); return hres; }
*ppvOut = NULL; return E_OUTOFMEMORY; }
#ifdef DEBUG
//
// FEATURE - Move g_dwDeskStatTrace into ccshell.ini to prevent recompiles.
//
DWORD g_dwDeskStatTrace = 2; static DWORD g_dwIndent = 0; static const TCHAR c_szDotDot[] = TEXT("..");
#define MAX_INDENTATION_VALUE 0x20
void EnterProcDS(DWORD dwTraceLevel, LPSTR pszFmt, ...) { TCHAR szFmt[1000]; va_list arglist;
SHAnsiToTChar(pszFmt, szFmt, ARRAYSIZE(szFmt)); if (dwTraceLevel <= g_dwDeskStatTrace) { TCHAR szOutput[1000]; szOutput[0] = TEXT('\0');
for (DWORD i=0; i<g_dwIndent; i++) { StringCchCat(szOutput, ARRAYSIZE(szOutput), c_szDotDot); // truncation fine, this is debug spew
}
int cchOutput = lstrlen(szOutput); va_start(arglist, pszFmt); StringCchVPrintf(szOutput + cchOutput, ARRAYSIZE(szOutput) - cchOutput, szFmt, arglist); // truncation fine, this is debug spew
va_end(arglist);
TraceMsg(TF_DESKSTAT, "%s", szOutput);
// We don't want this value to get out of hand because of
// unmatched Enter and Exit calls in functions (which will
// trash the stack).
if (g_dwIndent < MAX_INDENTATION_VALUE) g_dwIndent++; } }
void ExitProcDS(DWORD dwTraceLevel, LPSTR pszFmt, ...) { TCHAR szFmt[1000]; TCHAR szOutput[1000]; va_list arglist;
SHAnsiToTChar(pszFmt, szFmt, ARRAYSIZE(szFmt)); if (dwTraceLevel <= g_dwDeskStatTrace) { //This can happen if the Enter and Exit procs are unmatched.
if (g_dwIndent > 0) g_dwIndent--;
szOutput[0] = TEXT('\0');
for (DWORD i=0; i<g_dwIndent; i++) { StringCchCat(szOutput, ARRAYSIZE(szOutput), c_szDotDot); // truncation fine, this is debug spew
}
int cchOutput = lstrlen(szOutput); va_start(arglist, pszFmt); StringCchVPrintf(szOutput + cchOutput, ARRAYSIZE(szOutput) - cchOutput, szFmt, arglist); // truncation fine, this is debug spew
va_end(arglist);
TraceMsg(TF_DESKSTAT, "%s", szOutput); } }
#endif
/*************************************************************************
* * IActiveDesktopP methods and helper functions * * IActiveDesktopP is a private interface used to implement helper * functionality that is used internally by the various shell binaries. * * Notes: * Getting an interface to IActiveDesktopP does not initialize the state * of the object such that member functions are able to call IActiveDesktop * member functions. This is so that it is a more lightweight implementation * and also simplifies the implementation of SetScheme. If a subsequent QI for * IActiveDesktop is performed then it will initialize properly and any member * function can then be called. * *************************************************************************/
//
// SetScheme
//
// Used to set the current scheme that the object will read and write to
// when it is initialized. This method must be called before a subsequent
// QI to IActiveDesktop is made.
//
HRESULT CActiveDesktop::SetScheme(LPCWSTR pwszSchemeName, DWORD dwFlags) { LPTSTR pszSchemeName, pszAlloc; int icch;
// Can't set the local scheme after we've been initialized...we can fix this
// later if necessary but for now it's simplest this way.
if (_fInitialized && (dwFlags & SCHEME_LOCAL)) return E_FAIL;
// Sanity checks
if (!pwszSchemeName || ((icch = lstrlenW(pwszSchemeName)) > MAX_PATH - 1)) return E_INVALIDARG;
pszSchemeName = (LPTSTR)pwszSchemeName;
if (dwFlags & SCHEME_CREATE) { LONG lRet; HKEY hkey, hkey2;
lRet = RegCreateKeyEx(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME_LOCATION, 0, NULL, 0, KEY_CREATE_SUB_KEY, NULL, &hkey, NULL); if (ERROR_SUCCESS == lRet) { lRet = RegCreateKeyEx(hkey, pszSchemeName, 0, NULL, 0, KEY_WRITE, NULL, &hkey2, NULL); if (ERROR_SUCCESS == lRet) { RegCloseKey(hkey2); } RegCloseKey(hkey); } if (ERROR_SUCCESS != lRet) { return E_FAIL; } }
if (dwFlags & SCHEME_LOCAL) { // The local case is easy - just copy the string to our local variable,
// it will be used when IActiveDesktop is initialized.
if (!(pszAlloc = (LPTSTR)LocalAlloc(LPTR, (icch + 1) * sizeof(TCHAR)))) return E_OUTOFMEMORY;
if (_pszScheme) LocalFree((HANDLE)_pszScheme);
_pszScheme = pszAlloc;
HRESULT hr = StringCchCopy(_pszScheme, icch + 1, pszSchemeName); if (FAILED(hr)) { return hr; } }
if (dwFlags & SCHEME_GLOBAL) { // Update the registry with the new global scheme value
if (dwFlags & SCHEME_DISPLAY) SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_DISPLAY, REG_SZ, pszSchemeName, CbFromCch(lstrlen(pszSchemeName) + 1)); if (dwFlags & SCHEME_EDIT) SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, REG_VAL_SCHEME_EDIT, REG_SZ, pszSchemeName, CbFromCch(lstrlen(pszSchemeName) + 1)); }
if (dwFlags & (SCHEME_REFRESH | SCHEME_UPDATE)) { DWORD dwUpdateFlags = AD_APPLY_FORCE | AD_APPLY_HTMLGEN | AD_APPLY_SAVE; if (dwFlags & SCHEME_REFRESH) dwUpdateFlags |= (AD_APPLY_REFRESH | AD_APPLY_DYNAMICREFRESH); _Initialize(); _fUseDynamicHtml=FALSE; ApplyChanges(dwUpdateFlags); }
return S_OK; }
HRESULT GetGlobalScheme(LPWSTR pwszScheme, LPDWORD lpdwcchBuffer, DWORD dwFlags) { DWORD cbScheme = *lpdwcchBuffer * sizeof(pwszScheme[0]); LONG lret = SHGetValueW(HKEY_CURRENT_USER, REG_DESKCOMP_SCHEME, (dwFlags & SCHEME_EDIT) ? REG_VAL_SCHEME_EDIT : REG_VAL_SCHEME_DISPLAY, NULL, pwszScheme, &cbScheme); if (ERROR_SUCCESS == lret) { *lpdwcchBuffer = lstrlenW(pwszScheme); } return (lret == ERROR_SUCCESS ? S_OK : E_FAIL); }
//
// GetScheme
//
//
HRESULT CActiveDesktop::GetScheme(LPWSTR pwszSchemeName, LPDWORD lpdwcchBuffer, DWORD dwFlags) { // Sanity checks
if (!pwszSchemeName || *lpdwcchBuffer == 0) return E_INVALIDARG;
if (dwFlags & SCHEME_LOCAL) { if (!_pszScheme) { HRESULT hres; // Special case if no local scheme has explicitly been selected yet.
// The default scheme is the global display scheme in this case.
if (SUCCEEDED(hres = GetGlobalScheme(pwszSchemeName, lpdwcchBuffer, SCHEME_DISPLAY))) { hres = SetScheme(pwszSchemeName, SCHEME_LOCAL); } return hres; }
SHTCharToUnicode(_pszScheme, pwszSchemeName, *lpdwcchBuffer); *lpdwcchBuffer = lstrlenW(pwszSchemeName); return S_OK; }
if (dwFlags & SCHEME_GLOBAL) { return GetGlobalScheme(pwszSchemeName, lpdwcchBuffer, dwFlags); }
return E_INVALIDARG; }
BOOL UpdateAllDesktopSubscriptions(IADesktopP2 *); HRESULT CActiveDesktop::UpdateAllDesktopSubscriptions() { ::UpdateAllDesktopSubscriptions(this); return S_OK; }
void CActiveDesktop::_GenerateHtmlBStrForComp(COMPONENTA *pComp, BSTR *pbstr) { ENTERPROC(2, "DS _GenerateHtmlBstrForComp"); if (_pStream = SHCreateMemStream(NULL, 0)) //Create a mem stream.
{ LARGE_INTEGER libMove = {0}; ULARGE_INTEGER libCurPos; // Since _pStream is setup, the following call will generate the component HTML into
// that stream.
_GenerateHtmlComponent(pComp);
//Get the size of the stream generated.
if (SUCCEEDED(_pStream->Seek(libMove, STREAM_SEEK_CUR, &libCurPos))) { //Allocare a BSTR big enough to hold our component HTML code.
if (*pbstr = SysAllocStringLen(NULL, (libCurPos.LowPart)/sizeof(WCHAR))) { _pStream->Seek(libMove, STREAM_SEEK_SET, NULL); _pStream->Read(*pbstr, libCurPos.LowPart, NULL); } }
//NOTE: The bStr is released by the caller.
ATOMICRELEASE(_pStream); } else TraceMsg(TF_WARNING, "DS _GenerateHtmlBstrForComp unable to create a mem stream"); EXITPROC(2, "DS _GenerateHtmlBstrForComp"); }
void CActiveDesktop::_UpdateStyleOfElement(IHTMLElement *pElem, LPCOMPONENTA lpCompA) { IHTMLStyle *pHtmlStyle; if (SUCCEEDED(pElem->get_style(&pHtmlStyle))) { long lPixelVal; VARIANT vVal; VARIANT vValNew;
if (SUCCEEDED(pHtmlStyle->get_pixelLeft(&lPixelVal)) && (lPixelVal != lpCompA->cpPos.iLeft)) { TraceMsg(TF_DYNAMICHTML, "iLeft changes from %d to %d", lPixelVal, lpCompA->cpPos.iLeft); pHtmlStyle->put_pixelLeft((long)(lpCompA->cpPos.iLeft)); } if (SUCCEEDED(pHtmlStyle->get_pixelTop(&lPixelVal)) && (lPixelVal != lpCompA->cpPos.iTop)) { TraceMsg(TF_DYNAMICHTML, "iTop changes from %d to %d", lPixelVal, lpCompA->cpPos.iTop); pHtmlStyle->put_pixelTop((long)(lpCompA->cpPos.iTop)); }
VariantInit(&vVal); if (SUCCEEDED(pHtmlStyle->get_width(&vVal))) //Get the width as BSTR to see if width attribute exists
{ //See if the width attribute exists now.
if ((vVal.vt == VT_BSTR) && (vVal.bstrVal == NULL)) { // Width attribute does not exist for this element; This means that
// this element has the default width (may be a picture shown in it's original width).
if (lpCompA->cpPos.dwWidth != COMPONENT_DEFAULT_WIDTH) { //Component's new width is different from the default width. So, set the new width.
TraceMsg(TF_DYNAMICHTML, "dwWidth changes from default to %d", lpCompA->cpPos.dwWidth); pHtmlStyle->put_pixelWidth((long)(lpCompA->cpPos.dwWidth)); } //else, nothing to do! (the widths match exactly).
} else { // Width attribute exists! That means that this element has a width other than the
// default width.
// See if the new width is the default width.
if (lpCompA->cpPos.dwWidth == COMPONENT_DEFAULT_WIDTH) { // The old width is NOT default; But, the new width is default. So, let's just
// remove the width attribute.
VariantInit(&vValNew); vValNew.vt = VT_BSTR; vValNew.bstrVal = NULL; pHtmlStyle->put_width(vValNew);
VariantClear(&vValNew); } else { //Get the existing width in pixels.
if (SUCCEEDED(pHtmlStyle->get_pixelWidth(&lPixelVal)) && (((DWORD)lPixelVal) != lpCompA->cpPos.dwWidth)) { TraceMsg(TF_DYNAMICHTML, "dwWidth changes from %d to %d", lPixelVal, lpCompA->cpPos.dwWidth); pHtmlStyle->put_pixelWidth((long)(lpCompA->cpPos.dwWidth)); } //else, nothing else to do because the widths match!
} } VariantClear(&vVal); } if (SUCCEEDED(pHtmlStyle->get_height(&vVal))) //Get the height as BSTR to see if height attribute exists
{ // See if the height attribute exists.
if ((vVal.vt == VT_BSTR) && (vVal.bstrVal == NULL)) { // Height attribute does not exist for this element; This means that
// this element has the default height (may be a picture shown in it's original height).
if (lpCompA->cpPos.dwHeight != COMPONENT_DEFAULT_HEIGHT) { //Component's new height is different from the default height. So, set the new height.
TraceMsg(TF_DYNAMICHTML, "dwHeight changes from default to %d", lpCompA->cpPos.dwHeight); pHtmlStyle->put_pixelHeight((long)(lpCompA->cpPos.dwHeight)); } //else, nothing to do! (the heights match exactly).
} else { // Height attribute exists! That means that this element has a height other than the
// default height.
// See if the new height is the default height.
if (lpCompA->cpPos.dwHeight == COMPONENT_DEFAULT_HEIGHT) { // The old height is NOT default; But, the new height is default. So, let's just
// remove the height attribute.
VariantInit(&vValNew); vValNew.vt = VT_BSTR; vValNew.bstrVal = NULL; pHtmlStyle->put_height(vValNew); //remove the height attribute!
VariantClear(&vValNew); } else { //Get the existing height in pixels and see if it is different.
if (SUCCEEDED(pHtmlStyle->get_pixelHeight(&lPixelVal)) && (((DWORD)lPixelVal) != lpCompA->cpPos.dwHeight)) { //Since the new height is different, let's use set the new height!
TraceMsg(TF_DYNAMICHTML, "dwHeight changes from %d to %d", lPixelVal, lpCompA->cpPos.dwHeight); pHtmlStyle->put_pixelHeight((long)(lpCompA->cpPos.dwHeight)); } //else, nothing else to do because the heights match!
} } VariantClear(&vVal); } if (SUCCEEDED(pHtmlStyle->get_zIndex(&vVal)) && (vVal.vt == VT_I4) && (vVal.lVal != lpCompA->cpPos.izIndex)) { TraceMsg(TF_DYNAMICHTML, "ZIndex changes from %d to %d", vVal.lVal, lpCompA->cpPos.izIndex); vVal.lVal = lpCompA->cpPos.izIndex; pHtmlStyle->put_zIndex(vVal); } VariantClear(&vVal); pHtmlStyle->Release(); }
//FEATURE: Should we check for and set the other attributes like "resizeable" etc.,?
}
BOOL CActiveDesktop::_UpdateIdOfElement(IHTMLElement *pElem, LPCOMPONENTA lpCompA) { BSTR bstrId; BOOL fWholeElementReplaced = FALSE; //Assume that the item id does not change.
//Check if the Id of the component and the element matches.
if (SUCCEEDED(pElem->get_id(&bstrId))) //get the old id
{
if (((DWORD)StrToIntW(bstrId)) != lpCompA->dwID) { // The following technic does not work in some versions of MSHTML.DLL
// because IHTMLElement->put_id() does not work unless the doc
// is in "design mode".
TCHAR szNewId[MAXID_LENGTH]; BSTR bstrNewId; HRESULT hr = StringCchPrintf(szNewId, ARRAYSIZE(szNewId), TEXT("%d"), lpCompA->dwID); if (SUCCEEDED(hr)) {
#ifdef DEBUG
{ TCHAR szOldId[MAXID_LENGTH]; if (SUCCEEDED(StringCchPrintf(szOldId, ARRAYSIZE(szOldId), TEXT("%d"), StrToIntW(bstrId)))) { TraceMsg(TF_DYNAMICHTML, "DHTML: Id changes from %s to %s", szOldId, szNewId); } } #endif //DEBUG
//The Ids do not match. So, let's set the new ID.
if (bstrNewId = SysAllocStringT(szNewId)) { hr = pElem->put_id(bstrNewId); SysFreeString(bstrNewId); }
if (FAILED(hr)) { //Replace the whole element's HTML with the newly generated HTML
BSTR bstrComp = 0; _GenerateHtmlBStrForComp(lpCompA, &bstrComp); if (bstrComp) { if (FAILED(hr = pElem->put_outerHTML(bstrComp))) TraceMsg(TF_DYNAMICHTML, "DHTML: put_outerHTML failed"); fWholeElementReplaced = TRUE; SysFreeString(bstrComp); } else { AssertMsg(FALSE, TEXT("DHTML: Unable to create html for comp")); } } } } //else the ids match; nothing to do!
SysFreeString(bstrId); //free the old id.
} else { AssertMsg(FALSE, TEXT("DS Unable to get the id of the element")); }
return fWholeElementReplaced; }
HRESULT CActiveDesktop::_UpdateHtmlElement(IHTMLElement *pElem) { VARIANT vData; TCHAR szUrl[INTERNET_MAX_URL_LENGTH]; TCHAR szSrcPath[INTERNET_MAX_URL_LENGTH]; LPTSTR lpszSrcPath; COMPONENTA CompA; int iIndex;
//If all components are disabled, then we nuke this component from HTML page.
if (!_co.fEnableComponents) { TraceMsg(TF_DYNAMICHTML, "DHTML: No item shown in this mode; so, deleting items"); pElem->put_outerHTML((BSTR)s_sstrEmpty.wsz); return S_OK; //Nothing else to do!
}
VariantInit(&vData); //First determine if the given element is currently a desktop item. (It could have been deleted)
//Get the element's "src" attribute.
if (FAILED(pElem->getAttribute((BSTR)s_sstrSRCMember.wsz, VARIANT_FALSE, &vData)) || (vData.vt == VT_NULL) || (vData.bstrVal == NULL)) { //If the subscribed_url is not present, then it could be an object with a classid.
if (FAILED(pElem->getAttribute((BSTR)s_sstrclassid.wsz, VARIANT_FALSE, &vData)) || (vData.vt == VT_NULL)) { //This element is does not have "src=" or "classid=" attributes. How did this ever
// become a desktop item with "name=deskmovr" or "name=deskmovrw"?? Hmmmmmm....!!!
#ifdef DEBUG
{ BSTR bstrHtmlForElem; // Get the HTML corresponding to the element that does not have a subscribed URL
if (SUCCEEDED(pElem->get_outerHTML(&bstrHtmlForElem))) { TraceMsg(TF_DYNAMICHTML, "DHTML: Rogue element: %s", bstrHtmlForElem); SysFreeString(bstrHtmlForElem); } } TraceMsg(TF_WARNING, "DHTML: Unable to get the subscribed_url or classid"); #endif
//Since this element does not seem to be a valid desktop item, let's nuke it!
pElem->put_outerHTML((BSTR)s_sstrEmpty.wsz); //delete this element.
return (E_FAIL); //Nothing else to for this element! It's gone!!!
} if ((vData.vt == VT_NULL) || (vData.bstrVal == NULL)) return E_FAIL; ASSERT(vData.vt == VT_BSTR); ASSERT(StrCmpNW(vData.bstrVal, L"clsid:", lstrlen(TEXT("clsid:"))) == 0); SHUnicodeToTChar(vData.bstrVal + lstrlen(TEXT("clsid:")), szUrl, ARRAYSIZE(szUrl)); lpszSrcPath = szUrl; //For classid, the SrcPath and the Url are the same.
} else { DWORD dwSize; if (vData.bstrVal == NULL) return (E_FAIL); ASSERT(vData.vt == VT_BSTR); SHUnicodeToTChar(vData.bstrVal, szUrl, ARRAYSIZE(szUrl));
dwSize = ARRAYSIZE(szSrcPath); lpszSrcPath = szSrcPath; if (FAILED(PathCreateFromUrl(szUrl, lpszSrcPath, &dwSize, 0))) { lpszSrcPath = szUrl; } }
VariantClear(&vData); //We made a TCHAR copy above. So, ok to free this.
CompA.dwSize = sizeof(CompA);
// First use the Source path to Find the component; This is much more efficient because it
// involves no conversion from Path to Url and vice-versa.
if ((iIndex = _FindComponentBySource(lpszSrcPath, &CompA)) < 0) { // Could not find component using SrcPath!
// Let's try using the SrcUrl; This is less efficient.
iIndex = _FindComponentBySrcUrl(szUrl, &CompA); } if ((iIndex>= 0) && (CompA.fChecked)) { //The component is found and it is enabled.
TraceMsg(TF_DYNAMICHTML, "DHTML:Updating desktop item with URL: %s", szUrl);
// If the id changes, we replace the whole HTML for that element, so, no need to check for
// the individual styles.
if (!_UpdateIdOfElement(pElem, &CompA)) _UpdateStyleOfElement(pElem, &CompA); CompA.fDirty = TRUE; //Mark the component sothat we know that it had been updated.
UpdateComponentPrivate(iIndex, &CompA); } else { ASSERT((iIndex == -1) || (!CompA.fChecked)); //Component not found OR it is disabled!
TraceMsg(TF_DYNAMICHTML, "DHTML: Deleting desktop item with URL: %s, SrcPath:%s", szUrl, lpszSrcPath);
//The component is not present now. So, delete this element from the html page.
pElem->put_outerHTML((BSTR)s_sstrEmpty.wsz); }
return S_OK; }
//
// This code enumerates and then updates all the desktop item elements in the active desktop based
// on the current status of the active desktop items in the CActiveDesktop object (The current
// status is initialized by reading from the registry when ActiveDesktop object is initialized).
//
HRESULT CActiveDesktop::_UpdateDesktopItemHtmlElements(IHTMLDocument2 *pDoc) { HRESULT hres = S_OK; IHTMLElementCollection *pAllElements;
TraceMsg(TF_DYNAMICHTML, "DHTML: Updating Desktop html elements dynamically");
if (!_fInitialized) //If not yet initialized, initialize now because we need _co.fEnableComponents.
_Initialize();
// We need to check for a change in the background color only if there is no wallpaper or
// the wallpaper is a picture.
if (IsWallpaperPicture(_szSelectedWallpaper)) { COLORREF rgbDesktop; TCHAR szRgbDesktop[10]; VARIANT vColor; //Check to see if the background color has changed
rgbDesktop = GetSysColor(COLOR_DESKTOP);
hres = StringCchPrintf(szRgbDesktop, ARRAYSIZE(szRgbDesktop), TEXT("#%02lx%02lx%02lx"), GetRValue(rgbDesktop), GetGValue(rgbDesktop), GetBValue(rgbDesktop)); if (SUCCEEDED(hres)) { hres = pDoc->get_bgColor(&vColor); if (SUCCEEDED(hres) && (vColor.vt == VT_BSTR)) { BSTR bstrNewBgColor = SysAllocStringT(szRgbDesktop);
//Compare the new and the old strings.
if (StrCmpW(vColor.bstrVal, bstrNewBgColor)) { BSTR bstrOldBgColor = vColor.bstrVal; //Save the old bstr.
//So, the colors are different. Set the new color.
vColor.bstrVal = bstrNewBgColor; bstrNewBgColor = bstrOldBgColor; //Set it here sothat it is freed later.
if (FAILED(pDoc->put_bgColor(vColor))) { TraceMsg(TF_DYNAMICHTML, "DHTML: Unable to change the background color"); } }
if (bstrNewBgColor) SysFreeString(bstrNewBgColor); VariantClear(&vColor); } } }
//Get a collection of All elements in the Document
if (SUCCEEDED(hres)) { hres = pDoc->get_all(&pAllElements); if (SUCCEEDED(hres)) { VARIANT vName, vIndex; IDispatch *pDisp; int i; long lItemsEnumerated = 0; long lLength = 0;
#ifdef DEBUG
pAllElements->get_length(&lLength); TraceMsg(TF_DYNAMICHTML, "DHTML: Length of All elements:%d", lLength); #endif
for(i = 0; i <= 1; i++) { //Collect all the elements that have the name="DeskMovr" and then name="DeskMovrW"
vName.vt = VT_BSTR; vName.bstrVal = (BSTR)((i == 0) ? s_sstrDeskMovr.wsz : s_sstrDeskMovrW.wsz);
VariantInit(&vIndex); //We want to get all elements. So, vIndex is set to VT_EMPTY
if (SUCCEEDED(pAllElements->item(vName, vIndex, &pDisp)) && pDisp) //Collect all elements we want
{ IHTMLElementCollection *pDeskCollection; if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLElementCollection, (void **)&pDeskCollection))) { IUnknown *pUnk; IEnumVARIANT *pEnumVar; if (SUCCEEDED(pDeskCollection->get_length(&lLength))) //Number of elements.
lItemsEnumerated += lLength; //Total number of items enumerated.
TraceMsg(TF_DYNAMICHTML, "DHTML: Enumerated %d number of elements", lLength); //Get the enumerator
if (SUCCEEDED(pDeskCollection->get__newEnum(&pUnk))) { if (SUCCEEDED(pUnk->QueryInterface(IID_IEnumVARIANT, (void **)&pEnumVar))) { VARIANT vElem; long lEnumCount = 0; DWORD cElementsFetched; while(SUCCEEDED(pEnumVar->Next(1, &vElem, &cElementsFetched)) && (cElementsFetched == 1)) { IHTMLElement *pElem; lEnumCount++; // Access the element from the variant.....!
if ((vElem.vt == VT_DISPATCH) && SUCCEEDED(vElem.pdispVal->QueryInterface(IID_IHTMLElement, (void **)&pElem))) { _UpdateHtmlElement(pElem); //Update the desktop element's attributes.
pElem->Release(); } VariantClear(&vElem); } //Number of items enumerated must be the same as the length
ASSERT(lEnumCount == lLength); pEnumVar->Release(); } pUnk->Release(); } pDeskCollection->Release(); } else { IHTMLElement *pElem; // The QI(IID_IHTMLElementCollection) has failed. It may be because only one item
// was returned rather than a collection.
if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLElement, (void **)&pElem))) { _UpdateHtmlElement(pElem); //Update the desktop element's attributes.
pElem->Release(); } else TraceMsg(TF_WARNING, "DHTML: Unable to get a collection or a single element"); } pDisp->Release(); } } // for loop enumeating "DeskMovr" and "DeskMovrW" items.
pAllElements->Release(); } }
// All the elements already present in the Doc have been updated. Now, let's add the
// new elements, if any.
if (_co.fEnableComponents) _InsertNewDesktopItems(pDoc); else { TraceMsg(TF_DYNAMICHTML, "DHTML: No components are to be shown in this mode;"); }
return hres; }
HRESULT CActiveDesktop::_InsertNewDesktopItems(IHTMLDocument2 *pDoc) { IHTMLElement *pBody; if (SUCCEEDED(pDoc->get_body(&pBody))) { if (_hdsaComponent) { int i, iCount;
iCount = DSA_GetItemCount(_hdsaComponent); for (i=0; i<iCount; i++) { COMPONENTA comp; comp.dwSize = sizeof(comp);
if (DSA_GetItem(_hdsaComponent, i, &comp) != -1) { //Check if this is a newly added component AND it is enabled.
if ((!comp.fDirty) && comp.fChecked) { TraceMsg(TF_DYNAMICHTML, "DHTML: Inserted comp: %s", comp.szSource); //Yup! This is a newly added component!
BSTR bstrComp = 0; //This is a new component. Generate the HTML for the component.
_GenerateHtmlBStrForComp(&comp, &bstrComp);
//Insert the component.
pBody->insertAdjacentHTML((BSTR)s_sstrBeforeEnd.wsz, (BSTR)bstrComp);
//Free the string.
SysFreeString(bstrComp); } } else { TraceMsg(TF_WARNING, "DHTML: InsertNewComp: Unable to get component %d.", i); } } } pBody->Release(); }
return S_OK; }
//
// This function takes a pointer to the ActiveDesktop's ole obj, reads all the changes to be done
// from the registry and makes those changes to the various elements through dynamic HTML interfaces.
//
HRESULT CActiveDesktop::MakeDynamicChanges(IOleObject *pOleObj) {
IHTMLDocument2 *pDoc; HRESULT hres = E_FAIL;
ENTERPROC(2, "MakeDynamicChanges");
if (pOleObj && SUCCEEDED(pOleObj->QueryInterface(IID_IHTMLDocument2, (void **)&pDoc))) { // Enumerate all the active desktop components and ensure they are up to date.
_UpdateDesktopItemHtmlElements(pDoc);
pDoc->Release(); } else { TraceMsg(TF_WARNING, "DHTML: MakeDynamicChanges: Unable to get IHTMLDocument2"); } EXITPROC(2, "MakeDynamicChanges");
return(hres); }
//
// SetSafeMode
//
// Either puts the active desktop in safemode or restores it to the previous
// scheme before safemode was entered.
//
HRESULT CActiveDesktop::SetSafeMode(DWORD dwFlags) { //
// Make sure we are in active desktop mode.
//
SHELLSTATE ss = {0}; BOOL fSetSafeMode = (dwFlags & SSM_SET) != 0;
SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); if (ss.fDesktopHTML) { //
// All we need to do is switch the "display" scheme to "safemode" in order to
// go into safemode. To go out, we just switch the "display" scheme back to the
// previous "edit" scheme.
//
WCHAR wszEdit[MAX_PATH]; WCHAR wszDisplay[MAX_PATH]; DWORD dwcch = MAX_PATH;
if (SUCCEEDED(GetScheme(wszEdit, &dwcch, SCHEME_GLOBAL | SCHEME_EDIT))) { dwcch = MAX_PATH; if (SUCCEEDED(GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY))) { BOOL fInSafeMode = (StrCmpW(wszDisplay, REG_DESKCOMP_SAFEMODE_SUFFIX_L) == 0);
if (fSetSafeMode != fInSafeMode) { LPWSTR lpwstr; DWORD dwSchemeFlags = SCHEME_GLOBAL | SCHEME_DISPLAY; if (dwFlags & SSM_REFRESH) dwSchemeFlags |= SCHEME_REFRESH; if (dwFlags & SSM_UPDATE) dwSchemeFlags |= SCHEME_UPDATE;
lpwstr = fSetSafeMode ? REG_DESKCOMP_SAFEMODE_SUFFIX_L : wszEdit;
SetScheme(lpwstr, dwSchemeFlags); } } } } return S_OK; }
//
// EnsureUpdateHTML
//
// Ensures that the current html file present on the disk is in sync
// with the registry information for the current active desktop scheme. If
// it is not in sync then a fresh copy of the file is generated from the
// registry for the current scheme.
//
HRESULT CActiveDesktop::EnsureUpdateHTML(void) { DWORD dwFlags = 0; DWORD dwDataLength = sizeof(DWORD); LONG lRet; TCHAR szDeskcomp[MAX_PATH]; TCHAR szDesktopFile[MAX_PATH]; DWORD dwRestrictUpdate; DWORD dwRestrict = SHRestricted2W(REST_NoChannelUI, NULL, 0); DWORD dwSize = sizeof(dwRestrictUpdate); BOOL fComponentsDirty = FALSE; //Assume that the components are NOT dirty!
DWORD dwVersion; DWORD dwMinorVersion; BOOL fStaleInfoInReg = FALSE; BOOL fComponentsZoomDirty = FALSE; static BOOL s_fNoDeskComp = (BOOL)-1; static BOOL s_fNoWallpaper = (BOOL)-1; BOOL fNoDeskComp = SHRestricted(REST_NODESKCOMP); BOOL fNoWallpaper = SHRestricted(REST_NOHTMLWALLPAPER); BOOL fAdminComponent = FALSE; HKEY hkey = NULL; HKEY hkeyTime; FILETIME ftAdminCompKey;
if (ERROR_SUCCESS != SHGetValue(HKEY_CURRENT_USER, REG_DESKCOMP_COMPONENTS_ROOT, REG_VAL_GENERAL_RESTRICTUPDATE, NULL, &dwRestrictUpdate, &dwSize)) { dwRestrictUpdate = 0; }
GetRegLocation(szDeskcomp, ARRAYSIZE(szDeskcomp), REG_DESKCOMP_COMPONENTS, NULL);
//See if this branch of registry is old
if ((lRet = SHGetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_COMP_VERSION, NULL, &dwVersion, &dwDataLength)) == ERROR_SUCCESS) { if (dwVersion < CUR_DESKHTML_VERSION) { fStaleInfoInReg = TRUE; } else { //Major versions are equal. Check minor versions.
if ((lRet = SHGetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_COMP_MINOR_VERSION, NULL, &dwMinorVersion, &dwDataLength)) == ERROR_SUCCESS) { if (dwMinorVersion != CUR_DESKHTML_MINOR_VERSION) fStaleInfoInReg = TRUE; } else { fStaleInfoInReg = TRUE; } } } else { fStaleInfoInReg = TRUE; }
dwDataLength = sizeof(DWORD);
//Check the dirty bit to see if we need to re-generate the desktop html
if ((lRet = SHGetValue(HKEY_CURRENT_USER, szDeskcomp, REG_VAL_COMP_GENFLAGS, NULL, &dwFlags, &dwDataLength)) == ERROR_SUCCESS) { if (IsFlagSet(dwFlags, COMPONENTS_DIRTY)) fComponentsDirty = TRUE; if (IsFlagSet(dwFlags, COMPONENTS_ZOOMDIRTY)) fComponentsZoomDirty = TRUE; }
// See if we need to add/delete an administrator added desktop component now
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REG_DESKCOMP_ADMINCOMP_ROOT, 0, KEY_READ, &hkey)) { FILETIME ftLast; DWORD cbData = sizeof(ftLast); DWORD dwType;
ZeroMemory(&ftLast, sizeof(ftLast));
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, REG_DESKCOMP, 0, KEY_READ, &hkeyTime)) { SHQueryValueEx(hkeyTime, TEXT("LastSyncedTime"), NULL, &dwType, (LPBYTE)&ftLast, &cbData); RegCloseKey(hkeyTime); }
RegQueryInfoKey(hkey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &ftAdminCompKey);
if (CompareFileTime(&ftAdminCompKey, &ftLast) == 1) { WCHAR wszDisplay[MAX_PATH]; DWORD dwcch = MAX_PATH;
if (FAILED(GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY)) || (StrCmpW(wszDisplay, REG_DESKCOMP_SAFEMODE_SUFFIX_L) != 0)) { // We're not in safe mode, it's OK to add the components
fAdminComponent = TRUE; } } }
// 99/03/23 #237632 vtan: If the monitor arrangement has been changed from underneath
// the user (perhaps by another user) then make sure that the components are in valid
// positions. If not then snap them back into the visible space and mark them as dirty
// so that the desktop.htt file is regenerated.
_Initialize(); if (_hdsaComponent) { int i, iComponentCount;;
iComponentCount = DSA_GetItemCount(_hdsaComponent); for (i = 0; i < iComponentCount; ++i) { COMPONENTA *pComponent;
pComponent = reinterpret_cast<COMPONENTA*>(DSA_GetItemPtr(_hdsaComponent, i)); if (pComponent != NULL) { BOOL bChangedPosition = FALSE, bChangedSize = FALSE;
if (!SHIsTempDisplayMode()) //Modify the positions only if we are not in a temp mode change.
ValidateComponentPosition(&pComponent->cpPos, pComponent->dwCurItemState, pComponent->iComponentType, &bChangedPosition, &bChangedSize); if (bChangedPosition || bChangedSize) { TBOOL(UpdateComponentPrivate(i, pComponent)); fComponentsDirty = TRUE; } } } }
if (FAILED(GetPerUserFileName(szDesktopFile, ARRAYSIZE(szDesktopFile), DESKTOPHTML_FILENAME))) { szDesktopFile[0] = 0; }
if (fComponentsDirty || fComponentsZoomDirty || fStaleInfoInReg || fAdminComponent || fNoDeskComp != s_fNoDeskComp || fNoWallpaper != s_fNoWallpaper || (dwRestrictUpdate != dwRestrict) || !PathFileExistsAndAttributes(szDesktopFile, NULL)) //See if the file exists!
{
// Clear out any html wallpaper if it exists and the restriction is set
if (fNoWallpaper != s_fNoWallpaper) { if (fNoWallpaper && !IsWallpaperPicture(_szSelectedWallpaper)) SetWallpaper(L"", 0); s_fNoWallpaper = fNoWallpaper; }
// Disable components if the restriction is set
if (fNoDeskComp != s_fNoDeskComp) { // We can't set fEnableComponents to FALSE because there is no way via the UI
// for the user to turn it back on again if the restriction is lifted. Instead we add
// special case code to _GenerateHtml that checks the restriction too.
// _co.fEnableComponents = !fNoDeskComp;
s_fNoDeskComp = fNoDeskComp; }
if (fAdminComponent) { COMPONENT comp; TCHAR pszAdminComp[INTERNET_MAX_URL_LENGTH]; CHAR szUrl[INTERNET_MAX_URL_LENGTH]; CHAR * pszUrl; CHAR * pszUrlList; TCHAR * aszAdminComp[] = {REG_VAL_ADMINCOMP_ADD, REG_VAL_ADMINCOMP_DELETE, NULL}; int i = 0;
comp.dwSize = sizeof(comp); comp.dwCurItemState = IS_SPLIT | IS_ADJUSTLISTVIEW;
while (aszAdminComp[i]) { dwDataLength = sizeof(pszAdminComp); // The reg value contains an array of space separated urls - currently we support adding and deleting
// a desktop item via this mechanism.
if (SHQueryValueEx(hkey, aszAdminComp[i], NULL, NULL, (LPBYTE)pszAdminComp, &dwDataLength) == ERROR_SUCCESS) { SHTCharToAnsi(pszAdminComp, szUrl, ARRAYSIZE(szUrl)); pszUrlList = szUrl; while (pszUrl = StrTokEx(&pszUrlList, " ")) { SHAnsiToUnicode(pszUrl, comp.wszSource, ARRAYSIZE(comp.wszSource)); dwDataLength = ARRAYSIZE(comp.wszSource); ParseURLFromOutsideSourceW(comp.wszSource, comp.wszSource, &dwDataLength, NULL); if (lstrcmp(aszAdminComp[i], REG_VAL_ADMINCOMP_ADD) == 0) { AddUrl(NULL, (LPCWSTR)comp.wszSource, &comp, ADDURL_SILENT); fComponentsZoomDirty = TRUE; } else { RemoveDesktopItem((LPCOMPONENT)&comp, 0); } } } i++; } SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP, TEXT("LastSyncedTime"), REG_BINARY, (LPVOID)&ftAdminCompKey, sizeof(ftAdminCompKey));
}
// Go through the entire list of desktop components and ensure any split/fullscreen
// components are at their correct size/location.
if (fComponentsZoomDirty) { if (_hdsaComponent) { int i; for (i = 0; i < DSA_GetItemCount(_hdsaComponent); i++) { COMPONENTA * pcompT; if (pcompT = (COMPONENTA *)DSA_GetItemPtr(_hdsaComponent, i)) { if (ISZOOMED(pcompT)) { BOOL fAdjustListview = (pcompT->dwCurItemState & IS_ADJUSTLISTVIEW); ZoomComponent(&pcompT->cpPos, pcompT->dwCurItemState, fAdjustListview); if (fAdjustListview) pcompT->dwCurItemState &= ~IS_ADJUSTLISTVIEW; } } } SetDesktopFlags(COMPONENTS_ZOOMDIRTY, 0); } }
// NOTE #1: The above initialization would have changed the Z-order because of
// SortAndRationalize and so we need to APPLY_SAVE here.
// Warning: APPLY_SAVE changes the dwID field of components. This should not
// be a problem because we do this just before generating a new HTML file.
// NOTE #2: Do NOT use AD_APPLY_FORCE here. That sets the _fPatternDirty too and
// that causes a SystemParametersInfo() call which results in WM_SYSCOLORCHANGE
// and this causes a refresh. So, we set the dirty bit explicitly here.
_fDirty = TRUE; // See Note#2 above.
ApplyChanges(AD_APPLY_SAVE | AD_APPLY_HTMLGEN); lRet = ERROR_SUCCESS; if (dwRestrictUpdate != dwRestrict) SHSetValue(HKEY_CURRENT_USER, REG_DESKCOMP_COMPONENTS_ROOT, REG_VAL_GENERAL_RESTRICTUPDATE, NULL, &dwRestrict, sizeof(dwRestrict)); }
if (hkey) { RegCloseKey(hkey); }
return (lRet == ERROR_SUCCESS ? S_OK : E_FAIL); }
//
// ReReadWallpaper()
// If the wallpaper was read when the active desktop was disabled, we would have read it from
// the old location. Now, if the active desktop is turned ON, then we need to re-read the wallpaper
// from the new location. We need to do this iff the wallpaper has not been changed in the mean-while
//
HRESULT CActiveDesktop::ReReadWallpaper(void) { if ((!_fDirty) || (!_co.fActiveDesktop)) //If nothing has changed OR if active desktop is OFF,
return(S_FALSE); // then nothing to do!
//ActiveDesktop is ON in our object. Read current shell state.
SHELLSTATE ss = {0}; SHGetSetSettings(&ss, SSF_DESKTOPHTML, FALSE); if (ss.fDesktopHTML) return(S_FALSE); // Active Desktop state hasn't changed. So, nothing to do!
//So, Active desktop was originally OFF and now it is turned ON.
//If if someone changed the wallpaper, we should not mess with it.
if (_fWallpaperDirty || _fWallpaperChangedDuringInit) return(S_FALSE);
// No one has changed the wallpaper. So, we must re-read it from the new wallpaper location
// sothat we get the correct wallpaper for the active desktop mode.
_ReadWallpaper(TRUE);
return(S_OK); }
//
// GetADObjectFlags()
//
// Get the Active Desktop object's internal flags
//
HRESULT CActiveDesktop::GetADObjectFlags(LPDWORD lpdwFlags, DWORD dwMask) { ASSERT(lpdwFlags); *lpdwFlags = 0; //Init the flags
if ((dwMask & GADOF_DIRTY) && _fDirty) *lpdwFlags |= GADOF_DIRTY;
return(S_OK); }
HRESULT ForceFullRefresh(void) { HWND hwndShell = GetShellWindow();
//Force a SHRefresh with this dummy call
SHGetSetSettings(NULL, 0, TRUE); SendMessage(hwndShell, DTM_MAKEHTMLCHANGES, (WPARAM)0, (LPARAM)0L); //Can't use dynamic html. We have to refresh the whole page.
SendMessage(hwndShell, WM_WININICHANGE, SPI_SETDESKWALLPAPER, (LPARAM)c_szRefreshDesktop);
return S_OK; }
HRESULT CActiveDesktop::Read(LPCOLESTR pszPropName, VARIANT *pVar, IErrorLog *pErrorLog) { HRESULT hr = E_INVALIDARG;
if (pszPropName && pVar) { hr = E_FAIL;
if (StrCmpIW(pszPropName, c_wszPropName_IgnorePolicies) == 0) { pVar->vt = VT_BOOL; pVar->boolVal = (_fIgnoreAddRemovePolicies ? VARIANT_TRUE : VARIANT_TRUE); hr = S_OK; } else if (StrCmpIW(pszPropName, c_wszPropName_TSPerfBGPolicy) == 0) { BOOL fPolicySet = (IsTSPerfFlagEnabled(TSPerFlag_NoADWallpaper) || IsTSPerfFlagEnabled(TSPerFlag_NoWallpaper)); //No policy is set!
pVar->vt = VT_BOOL; pVar->boolVal = (fPolicySet ? VARIANT_TRUE : VARIANT_TRUE); hr = S_OK; } } return hr; }
HRESULT CActiveDesktop::Write(LPCOLESTR pszPropName, VARIANT *pVar) { HRESULT hr = E_INVALIDARG;
if (pszPropName && pVar) { hr = E_FAIL; if ((StrCmpIW(pszPropName, c_wszPropName_IgnorePolicies) == 0) && (VT_BOOL == pVar->vt)) { _fIgnoreAddRemovePolicies = (VARIANT_TRUE == pVar->boolVal); hr = S_OK; } else if ((StrCmpIW(pszPropName, c_wszPropName_TSPerfBGPolicy) == 0) && (VT_BOOL == pVar->vt)) { ForceFullRefresh(); hr = S_OK; } }
return hr; }
/***
*char *StrTokEx(pstring, control) - tokenize string with delimiter in control * *Purpose: * StrTokEx considers the string to consist of a sequence of zero or more * text tokens separated by spans of one or more control chars. the first * call, with string specified, returns a pointer to the first char of the * first token, and will write a null char into pstring immediately * following the returned token. when no tokens remain * in pstring a NULL pointer is returned. remember the control chars with a * bit map, one bit per ascii char. the null char is always a control char. * *Entry: * char **pstring - ptr to ptr to string to tokenize * char *control - string of characters to use as delimiters * *Exit: * returns pointer to first token in string, * returns NULL when no more tokens remain. * pstring points to the beginning of the next token. * *WARNING!!! * upon exit, the first delimiter in the input string will be replaced with '\0' * * copied from iert.lib *******************************************************************************/
extern "C" char * __cdecl StrTokEx(char ** spstring, const char * scontrol) { unsigned char **pstring = (unsigned char**) spstring; unsigned char *control = (unsigned char*) scontrol;
unsigned char *str; const unsigned char *ctrl = control; unsigned char map[32]; int count;
unsigned char *tokenstr;
if (*pstring == NULL) return NULL; /* Clear control map */ for (count = 0; count < 32; count++) map[count] = 0;
/* Set bits in delimiter table */ do { map[*ctrl >> 3] |= (1 << (*ctrl & 7)); } while (*ctrl++);
/* Initialize str. */ str = *pstring; /* Find beginning of token (skip over leading delimiters). Note that
* there is no token if this loop sets str to point to the terminal * null (*str == '\0') */ while ( (map[*str >> 3] & (1 << (*str & 7))) && *str ) str++;
tokenstr = str;
/* Find the end of the token. If it is not the end of the string,
* put a null there. */ for ( ; *str ; str++ ) { if ( map[*str >> 3] & (1 << (*str & 7)) ) { *str++ = '\0'; break; } }
/* string now points to beginning of next token */ *pstring = str;
/* Determine if a token has been found. */ if ( tokenstr == str ) return NULL; else return (char*)tokenstr; }
|