#include "stdafx.h" #pragma hdrstop #define _BROWSEUI_ // Make functions exported from browseui as stdapi (as they are delay loaded) #include "iethread.h" #include "browseui.h" #include "securent.h" #include // MAX_GUID_STRING_LEN static void EmptyListview(IActiveDesktop * pActiveDesktop, HWND hwndLV); #define DXA_GROWTH_CONST 10 #define COMP_CHECKED 0x00002000 #define COMP_UNCHECKED 0x00001000 #define GALRET_NO 0x00000001 #define GALRET_NEVER 0x00000002 #define CCompPropSheetPage CCompPropSheetPage const static DWORD aDesktopItemsHelpIDs[] = { // Context Help IDs IDC_COMP_DESKTOPWEBPAGES_TITLE1, IDH_DISPLAY_WEB_ACTIVEDESKTOP_LIST, IDC_COMP_LIST, IDH_DISPLAY_WEB_ACTIVEDESKTOP_LIST, IDC_COMP_NEW, IDH_DISPLAY_WEB_NEW_BUTTON, IDC_COMP_DELETE, IDH_DISPLAY_WEB_DELETE_BUTTON, IDC_COMP_PROPERTIES, IDH_DISPLAY_WEB_PROPERTIES_BUTTON, IDC_COMP_SYNCHRONIZE,IDH_DISPLAY_WEB_SYNCHRONIZE_BUTTON, IDC_COMP_DESKTOPICONS_GROUP, IDH_DESKTOPITEMS_DESKTOPICONS_GROUP, IDC_DESKTOP_ICON_MYDOCS, IDH_DESKTOPITEMS_DESKTOPICONS_GROUP, IDC_DESKTOP_ICON_MYCOMP, IDH_DESKTOPITEMS_DESKTOPICONS_GROUP, IDC_DESKTOP_ICON_MYNET, IDH_DESKTOPITEMS_DESKTOPICONS_GROUP, IDC_DESKTOP_ICON_IE, IDH_DESKTOPITEMS_DESKTOPICONS_GROUP, IDC_COMP_CHANGEDESKTOPICON_LABEL, IDH_DESKTOPITEMS_ICONS, IDC_DESKTOP_ICONS, IDH_DESKTOPITEMS_ICONS, // List of icons IDC_CHANGEICON2, IDH_DESKTOPITEMS_CHANGEICON2, // Change Icon Button IDC_ICONDEFAULT, IDH_DESKTOPITEMS_ICONDEFAULT, // Default Icon Button IDC_COMP_DESKTOPWEBPAGES_LABEL, IDH_DISPLAY_WEB_ACTIVEDESKTOP_LIST, IDC_DESKCLNR_CHECK, IDH_DESKTOPITEMS_DESKCLNR_CHECK, IDC_DESKCLNR_MOVEUNUSED, IDH_DESKTOPITEMS_DESKCLNR_CHECK, IDC_DESKCLNR_RUNWIZARD, IDH_DESKTOPITEMS_DESKCLNR_RUNNOW, IDC_COMP_DESKTOPWEBPAGES_CHECK, IDH_DESKTOPITEMS_LOCKDESKITEMS_CHECK, IDC_COMP_DESKTOPWEBPAGES_TITLE2, IDH_DESKTOPITEMS_LOCKDESKITEMS_CHECK, 0, 0 }; #define SZ_HELPFILE_DESKTOPITEMS TEXT("display.hlp") // registry paths defined in shell\applet\cleanup\fldrclnr\cleanupwiz.h #define REGSTR_DESKTOP_CLEANUP TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Explorer\\Desktop\\CleanupWiz") #define REGSTR_VAL_DONTRUN TEXT("NoRun") extern int g_iRunDesktopCleanup; typedef struct { WCHAR wszURL[INTERNET_MAX_URL_LENGTH]; SUBSCRIPTIONINFO si; } BACKUPSUBSCRIPTION; const LPCWSTR s_Icons[] = { L"CLSID\\{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\DefaultIcon:DefaultValue", // My Computer L"CLSID\\{450D8FBA-AD25-11D0-98A8-0800361B1103}\\DefaultIcon:DefaultValue", // My Documents L"CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\DefaultIcon:DefaultValue", // My Network Places L"CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon:full", // Recycle Bin (Full) L"CLSID\\{645FF040-5081-101B-9F08-00AA002F954E}\\DefaultIcon:empty", // Recycle Bin (Empty) }; IActiveDesktop * g_pActiveDeskAdv = NULL; // We need to keep a different copy than g_pActiveDesk extern DWORD g_dwApplyFlags; // Extract Icon from a file in proper Hi or Lo color for current system display // // from FrancisH on 6/22/95 with mods by TimBragg HRESULT ExtractPlusColorIcon(LPCTSTR szPath, int nIndex, HICON *phIcon, UINT uSizeLarge, UINT uSizeSmall) { IShellLink * psl; HRESULT hres; HICON hIcons[2]; // MUST! - provide for TWO return icons *phIcon = NULL; if (SUCCEEDED(hres = CoCreateInstance(CLSID_ShellLink, NULL, CLSCTX_INPROC_SERVER, IID_PPV_ARG(IShellLink, &psl)))) { if (SUCCEEDED(hres = psl->SetIconLocation(szPath, nIndex))) { IExtractIcon *pei; if (SUCCEEDED(hres = psl->QueryInterface(IID_PPV_ARG(IExtractIcon, &pei)))) { if (SUCCEEDED(hres = pei->Extract(szPath, nIndex, &hIcons[0], &hIcons[1], (UINT)MAKEWPARAM((WORD)uSizeLarge, (WORD)uSizeSmall)))) { DestroyIcon(hIcons[1]); *phIcon = hIcons[0]; // Return first icon to caller } pei->Release(); } } psl->Release(); } return hres; } // end ExtractPlusColorIcon() BOOL AreEditAndDisplaySchemesDifferent(IActiveDesktop * pActiveDesktop) { BOOL fAreDifferent = FALSE; IActiveDesktopP * piadp; if (SUCCEEDED(pActiveDesktop->QueryInterface(IID_PPV_ARG(IActiveDesktopP, &piadp)))) { WCHAR wszEdit[MAX_PATH]; WCHAR wszDisplay[MAX_PATH]; DWORD dwcch = ARRAYSIZE(wszEdit); // If the edit scheme and display scheme are different, then we need to make // sure we force an update. if (SUCCEEDED(piadp->GetScheme(wszEdit, &dwcch, SCHEME_GLOBAL | SCHEME_EDIT))) { dwcch = ARRAYSIZE(wszDisplay); if (SUCCEEDED(piadp->GetScheme(wszDisplay, &dwcch, SCHEME_GLOBAL | SCHEME_DISPLAY))) { if (StrCmpW(wszDisplay, wszEdit)) { fAreDifferent = TRUE; } } } piadp->Release(); } return fAreDifferent; } HRESULT ActiveDesktop_CopyDesktopComponentsState(IN IActiveDesktop * pADSource, IN IActiveDesktop * pADDest) { int nCompCount; int nIndex; COMPONENT comp = {sizeof(comp)}; IPropertyBag *iPropBag = NULL; if(SUCCEEDED(pADDest->QueryInterface(IID_PPV_ARG(IPropertyBag, &iPropBag)))) { //Inform the AD object to ignore policies. Otherwise, the following Remove and AddDesktopItem //calls will generate error messages if those policies were in effect. SHPropertyBag_WriteBOOL(iPropBag, c_wszPropName_IgnorePolicies, TRUE); } // Remove the desktop components from g_pActiveDesk because they will be replaced // with the ones from g_pActiveDeskAdv. pADDest->GetDesktopItemCount(&nCompCount, 0); for (nIndex = (nCompCount - 1); nIndex >= 0; nIndex--) { if (SUCCEEDED(pADDest->GetDesktopItem(nIndex, &comp, 0))) { pADDest->RemoveDesktopItem(&comp, 0); } } // Now copy the Desktop Components from g_pActiveDeskAdv to g_pActiveDesk. pADSource->GetDesktopItemCount(&nCompCount, 0); for (nIndex = 0; nIndex < nCompCount; nIndex++) { if (SUCCEEDED(pADSource->GetDesktopItem(nIndex, &comp, 0))) { pADDest->AddDesktopItem(&comp, 0); } } if(iPropBag) { //We have removed and added all the desktop items. We are done manipulating the AD object. // Now, signal the AD object to reset the policies bit. SHPropertyBag_WriteBOOL(iPropBag, c_wszPropName_IgnorePolicies, FALSE); iPropBag->Release(); } return S_OK; } HRESULT ActiveDesktop_CopyComponentOptionsState(IN IActiveDesktop * pADSource, IN IActiveDesktop * pADDest) { HRESULT hr; COMPONENTSOPT co; // Copy over the on or off state of ActiveDesktop co.dwSize = sizeof(COMPONENTSOPT); hr = pADSource->GetDesktopItemOptions(&co, 0); if (SUCCEEDED(hr)) { hr = pADDest->SetDesktopItemOptions(&co, 0); } return hr; } // In ActiveDesktop_CopyState, we try to do as much as we can. If we fail, we keep going, // but we still have to return E_FAIL if any part of our work failed. HRESULT ActiveDesktop_CopyState(IN IActiveDesktop * pADSource, IN IActiveDesktop * pADDest) { HRESULT hr = S_OK; WCHAR szPath[MAX_PATH]; WALLPAPEROPT wallPaperOtp = {0}; // The Advanced page allowed the user to change the state. We need to merge // the state from g_pActiveDeskAdv back into g_pActiveDesk if (FAILED(ActiveDesktop_CopyDesktopComponentsState(pADSource, pADDest))) { hr = E_FAIL; } if (FAILED(ActiveDesktop_CopyComponentOptionsState(pADSource, pADDest))) { hr = E_FAIL; } if (FAILED(pADSource->GetWallpaper(szPath, ARRAYSIZE(szPath), 0)) || FAILED(pADDest->SetWallpaper(szPath, 0))) { hr = E_FAIL; } if (FAILED(pADSource->GetPattern(szPath, ARRAYSIZE(szPath), 0)) || FAILED(pADDest->SetPattern(szPath, 0))) { hr = E_FAIL; } wallPaperOtp.dwSize = sizeof(wallPaperOtp); if (FAILED(pADSource->GetWallpaperOptions(&wallPaperOtp, 0)) || FAILED(pADDest->SetWallpaperOptions(&wallPaperOtp, 0))) { hr = E_FAIL; } return hr; } HRESULT MergeState() { // The Advanced page allowed the user to change the state. We need to merge // the state from g_pActiveDeskAdv back into g_pActiveDesk ActiveDesktop_CopyDesktopComponentsState(g_pActiveDeskAdv, g_pActiveDesk); // Copy over the on or off state of ActiveDesktop COMPONENTSOPT co; co.dwSize = sizeof(COMPONENTSOPT); g_pActiveDeskAdv->GetDesktopItemOptions(&co, 0); BOOL fActiveDesktop = co.fActiveDesktop; g_pActiveDesk->GetDesktopItemOptions(&co, 0); co.fActiveDesktop = fActiveDesktop; // Replace only this option. g_pActiveDesk->SetDesktopItemOptions(&co, 0); // If the edit scheme and display scheme are different, then we need to make // sure we force an update. if (AreEditAndDisplaySchemesDifferent(g_pActiveDeskAdv)) { g_dwApplyFlags |= AD_APPLY_FORCE; } return S_OK; } HRESULT SHPropertyBag_ReadIcon(IN IPropertyBag * pAdvPage, IN BOOL fOldIcon, IN int nIndex, IN LPWSTR pszPath, IN DWORD cchSize, IN int * pnIcon) { HRESULT hr = E_INVALIDARG; if (nIndex < ARRAYSIZE(s_Icons)) { WCHAR szPropName[MAX_URL_STRING]; hr = StringCchCopy(szPropName, ARRAYSIZE(szPropName), s_Icons[nIndex]); if (SUCCEEDED(hr)) { if (fOldIcon) { // Indicate we want the old icon LPWSTR pszToken = StrChrW(szPropName, L':'); if (pszToken) { pszToken[0] = L';'; } } hr = SHPropertyBag_ReadStr(pAdvPage, szPropName, pszPath, cchSize); if (SUCCEEDED(hr)) { *pnIcon= PathParseIconLocation(pszPath); } } } return hr; } HRESULT SHPropertyBag_WriteIcon(IN IPropertyBag * pAdvPage, IN int nIndex, IN LPCWSTR pszPath, IN int nIcon) { HRESULT hr; if (nIndex >= ARRAYSIZE(s_Icons)) { hr = E_INVALIDARG; } else { WCHAR szPathAndIcon[MAX_PATH]; hr = StringCchPrintf(szPathAndIcon, ARRAYSIZE(szPathAndIcon), L"%s,%d", pszPath, nIcon); if (SUCCEEDED(hr)) { hr = SHPropertyBag_WriteStr(pAdvPage, s_Icons[nIndex], szPathAndIcon); } } return hr; } HRESULT CCompPropSheetPage::_LoadIconState(IN IPropertyBag * pAdvPage) { HRESULT hr = S_OK; int nIndex; // Move the values to the base dialog for (nIndex = 0; SUCCEEDED(hr) && (nIndex < ARRAYSIZE(_IconData)); nIndex++) { hr = SHPropertyBag_ReadIcon(pAdvPage, TRUE, nIndex, _IconData[nIndex].szOldFile, ARRAYSIZE(_IconData[nIndex].szOldFile), &_IconData[nIndex].iOldIndex); if (SUCCEEDED(hr)) { hr = SHPropertyBag_ReadIcon(pAdvPage, FALSE, nIndex, _IconData[nIndex].szNewFile, ARRAYSIZE(_IconData[nIndex].szNewFile), &_IconData[nIndex].iNewIndex); } } return hr; } HRESULT CCompPropSheetPage::_LoadDeskIconState(IN IPropertyBag * pAdvPage) { HRESULT hr = S_OK; // Copy the values from the base dialog for (int iStartPanel = 0; iStartPanel <= 1; iStartPanel++) { WCHAR wszPropName[MAX_GUID_STRING_LEN + 20]; for (int nIndex = 0; SUCCEEDED(hr) && (nIndex < NUM_DESKICONS); nIndex++) { // set defaults in case we fail the printfs _afHideIcon[iStartPanel][nIndex] = FALSE; if (iStartPanel == 1) { _afDisableCheckBox[nIndex] = FALSE; } hr = StringCchPrintf(wszPropName, ARRAYSIZE(wszPropName), c_wszPropNameFormat, c_awszSP[iStartPanel], c_aDeskIconId[nIndex].pwszCLSID); if (SUCCEEDED(hr)) { _afHideIcon[iStartPanel][nIndex] = SHPropertyBag_ReadBOOLDefRet(pAdvPage, wszPropName, FALSE); if(iStartPanel == 1) { hr = StringCchPrintf(wszPropName, ARRAYSIZE(wszPropName), c_wszPropNameFormat, POLICY_PREFIX, c_aDeskIconId[nIndex].pwszCLSID); if (SUCCEEDED(hr)) { _afDisableCheckBox[nIndex] = SHPropertyBag_ReadBOOLDefRet(pAdvPage, wszPropName, FALSE); } } } } } return hr; } HRESULT CCompPropSheetPage::_MergeDeskIconState(IN IPropertyBag * pAdvPage) { HRESULT hr = S_OK; // Move the values to the base dialog for (int iStartPanel = 0; SUCCEEDED(hr) && iStartPanel <= 1; iStartPanel++) { WCHAR wszPropName[MAX_GUID_STRING_LEN + 20]; for (int nIndex = 0; SUCCEEDED(hr) && (nIndex < NUM_DESKICONS); nIndex++) { hr = StringCchPrintf(wszPropName, ARRAYSIZE(wszPropName), c_wszPropNameFormat, c_awszSP[iStartPanel], c_aDeskIconId[nIndex].pwszCLSID); if (SUCCEEDED(hr)) { // Check if any icons have changed. hr = SHPropertyBag_WriteBOOL(pAdvPage, wszPropName, _afHideIcon[iStartPanel][nIndex]); } } } return hr; } HRESULT CCompPropSheetPage::_MergeIconState(IN IPropertyBag * pAdvPage) { HRESULT hr = S_OK; BOOL fHasIconsChanged = FALSE; int nIndex; // Move the values to the base dialog for (nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { // Check if any icons have changed. if ((_IconData[nIndex].iNewIndex != _IconData[nIndex].iOldIndex) || StrCmpI(_IconData[nIndex].szNewFile, _IconData[nIndex].szOldFile)) { hr = SHPropertyBag_WriteIcon(pAdvPage, nIndex, _IconData[nIndex].szNewFile, _IconData[nIndex].iNewIndex); fHasIconsChanged = TRUE; } } // Only switch to "Custom" if the icons changed. if (_punkSite && fHasIconsChanged) { // We need to tell the Theme tab to customize the theme. IPropertyBag * pPropertyBag; hr = _punkSite->QueryInterface(IID_PPV_ARG(IPropertyBag, &pPropertyBag)); if (SUCCEEDED(hr)) { // Tell the theme that we have customized the values. hr = SHPropertyBag_WriteInt(pPropertyBag, SZ_PBPROP_CUSTOMIZE_THEME, 0); pPropertyBag->Release(); } } return hr; } void CCompPropSheetPage::_AddComponentToLV(COMPONENTA *pcomp) { TCHAR szBuf[INTERNET_MAX_URL_LENGTH + 40]; if (SUCCEEDED(StringCchCopy(szBuf, ARRAYSIZE(szBuf), pcomp->szFriendlyName[0] ? pcomp->szFriendlyName : pcomp->szSource))) { // // Construct the listview item. // LV_ITEM lvi = {0}; lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = 0x7FFFFFFF; lvi.pszText = szBuf; lvi.lParam = pcomp->dwID; int index = ListView_InsertItem(_hwndLV, &lvi); if (index != -1) { ListView_SetItemState(_hwndLV, index, pcomp->fChecked ? COMP_CHECKED : COMP_UNCHECKED, LVIS_STATEIMAGEMASK); ListView_SetColumnWidth(_hwndLV, 0, LVSCW_AUTOSIZE); } } } void CCompPropSheetPage::_SetUIFromDeskState(BOOL fEmpty) { // // Disable redraws while we mess repeatedly with the listview contents. // SendMessage(_hwndLV, WM_SETREDRAW, FALSE, 0); if (fEmpty) { EmptyListview(g_pActiveDeskAdv, _hwndLV); } // // Add each component to the listview. // int cComp; g_pActiveDeskAdv->GetDesktopItemCount(&cComp, 0); for (int i=0; iGetDesktopItem(i, &comp, 0))) { COMPONENTA compA; compA.dwSize = sizeof(compA); WideCompToMultiComp(&comp, &compA); _AddComponentToLV(&compA); } } _fInitialized = TRUE; // // Reenable redraws. // SendMessage(_hwndLV, WM_SETREDRAW, TRUE, 0); InvalidateRect(_hwndLV, NULL, TRUE); } void CCompPropSheetPage::_EnableControls(HWND hwnd) { BOOL fEnable; COMPONENT comp = { sizeof(comp) }; BOOL fHaveSelection = FALSE; BOOL fSpecialComp = FALSE; //Is this a special component that can't be deleted? LPTSTR pszSource = NULL; // Read in the information about the selected component (if any). int iIndex = ListView_GetNextItem(_hwndLV, -1, LVNI_SELECTED); if (iIndex > -1) { LV_ITEM lvi = {0}; lvi.mask = LVIF_PARAM; lvi.iItem = iIndex; ListView_GetItem(_hwndLV, &lvi); if (SUCCEEDED(g_pActiveDeskAdv->GetDesktopItemByID( lvi.lParam, &comp, 0))) { fHaveSelection = TRUE; //Check if this is a special component. #ifdef UNICODE pszSource = (LPTSTR)comp.wszSource; #else SHUnicodeToAnsi(comp.wszSource, szCompSource, ARRAYSIZE(szCompSource)); pszSource = szCompSource; #endif fSpecialComp = !lstrcmpi(pszSource, MY_HOMEPAGE_SOURCE); } } // 98/08/19 vtan #142332: If there was a previously selected item // then reselect it and mark that there is now no previously selected // item. else if (_iPreviousSelection > -1) { ListView_SetItemState(_hwndLV, _iPreviousSelection, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); _iPreviousSelection = -1; // The above ListView_SetItemState results in LVN_ITEMCHANGED notification to _onNotify // function which inturn calls this _EnableControls again (recursively) and that call // enables/disables the buttons properly because now an item is selected. Nothing more // to do and hence this return. // This is done to fix Bug #276568. return; } EnableWindow(GetDlgItem(hwnd, IDC_COMP_NEW), _fAllowAdd); // // Delete button only enabled when an item is selected AND if it is NOT a special comp. // fEnable = _fAllowDel && fHaveSelection && !fSpecialComp; EnableWindow(GetDlgItem(hwnd, IDC_COMP_DELETE), fEnable); // // Properties button only enabled on URL based pictures // and websites. // fEnable = FALSE; if (_fAllowEdit && fHaveSelection) { switch (comp.iComponentType) { case COMP_TYPE_PICTURE: case COMP_TYPE_WEBSITE: //pszSource is already initialized if fHaveSelection is TRUE. if (PathIsURL(pszSource)) { fEnable = TRUE; } break; } } EnableWindow(GetDlgItem(hwnd, IDC_COMP_PROPERTIES), fEnable); // initialize the Lock Desktop Items button CheckDlgButton(hwnd, IDC_COMP_DESKTOPWEBPAGES_CHECK, _fLockDesktopItems); } HWND CCompPropSheetPage::_CreateListView(HWND hWndParent) { LV_ITEM lvI; // List view item structure TCHAR szTemp[MAX_PATH]; BOOL bEnable = FALSE; #ifdef JIGGLE_FIX RECT rc; #endif UINT flags = ILC_MASK | ILC_COLOR32; // Create a device independant size and location LONG lWndunits = GetDialogBaseUnits(); int iWndx = LOWORD(lWndunits); int iWndy = HIWORD(lWndunits); int iX = ((11 * iWndx) / 4); int iY = ((15 * iWndy) / 8); int iWidth = ((163 * iWndx) / 4); int iHeight = ((40 * iWndy) / 8); int nIndex; // Ensure that the common control DLL is loaded. InitCommonControls(); // Get the list view window _hWndList = GetDlgItem(hWndParent, IDC_DESKTOP_ICONS); if(_hWndList == NULL) return NULL; if(IS_WINDOW_RTL_MIRRORED(hWndParent)) { flags |= ILC_MIRROR; } // initialize the list view window // First, initialize the image lists we will need _hIconList = ImageList_Create(32, 32, flags, ARRAYSIZE(c_aIconRegKeys), 0 ); // create an image list for the icons // load the icons and add them to the image lists // get the icon files and indexes from the registry, including for the Default recycle bin for (nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { HICON hIcon = NULL; ExtractPlusColorIcon(_IconData[nIndex].szNewFile, _IconData[nIndex].iNewIndex, &hIcon, 0, 0); // Added this "if" to fix bug 2831. We want to use SHELL32.DLL // icon 0 if there is no icon in the file specified in the // registry (or if the registry didn't specify a file). if(hIcon == NULL) { if (GetSystemDirectory(szTemp, ARRAYSIZE(szTemp)) && PathAppend(szTemp, TEXT("shell32.dll")) && SUCCEEDED(StringCchCopy(_IconData[nIndex].szOldFile, ARRAYSIZE(_IconData[nIndex].szOldFile), szTemp)) && SUCCEEDED(StringCchCopy(_IconData[nIndex].szNewFile, ARRAYSIZE(_IconData[nIndex].szNewFile), szTemp))) { _IconData[nIndex].iOldIndex = _IconData[nIndex].iNewIndex = 0; ExtractPlusColorIcon(szTemp, 0, &hIcon, 0, 0); } } if (hIcon) { DWORD dwResult = ImageList_AddIcon(_hIconList, hIcon); // ImageList_AddIcon() does not take ownership of the icon, so we need to free it. DestroyIcon(hIcon); if (-1 == dwResult) { ImageList_Destroy(_hIconList); _hIconList = NULL; return NULL; } } } // Make sure that all of the icons were added if (ImageList_GetImageCount(_hIconList) < ARRAYSIZE(c_aIconRegKeys)) { ImageList_Destroy(_hIconList); _hIconList = NULL; return FALSE; } ListView_SetImageList(_hWndList, _hIconList, LVSIL_NORMAL); // Make sure the listview has WS_HSCROLL set on it. DWORD dwStyle = GetWindowLong(_hWndList, GWL_STYLE); SetWindowLong(_hWndList, GWL_STYLE, (dwStyle & (~WS_VSCROLL)) | WS_HSCROLL); // Finally, let's add the actual items to the control. Fill in the LV_ITEM // structure for each of the items to add to the list. The mask specifies // the the .pszText, .iImage, and .state members of the LV_ITEM structure are valid. lvI.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_STATE; lvI.state = 0; lvI.stateMask = 0; for(nIndex = 0; nIndex < ARRAYSIZE(c_aIconRegKeys); nIndex++ ) { TCHAR szAppend[64]; BOOL bRet = FALSE; if (IsEqualCLSID(*c_aIconRegKeys[nIndex].pclsid, CLSID_MyDocuments)) { LPITEMIDLIST pidl; HRESULT hr = SHGetSpecialFolderLocation(_hWndList, CSIDL_PERSONAL, &pidl); // Treat "My Files" differently because we will probably customize the "My" at run time. if (SUCCEEDED(hr)) { hr = SHGetNameAndFlags(pidl, SHGDN_INFOLDER, szTemp, ARRAYSIZE(szTemp), NULL); if (SUCCEEDED(hr)) { bRet = TRUE; } ILFree(pidl); } } else { bRet = IconGetRegNameString(c_aIconRegKeys[nIndex].pclsid, szTemp, ARRAYSIZE(szTemp)); } // if the title string was in the registry, else we have to use the default in our resources if( (bRet) && (lstrlen(szTemp) > 0)) { if( LoadString(HINST_THISDLL, c_aIconRegKeys[nIndex].iTitleResource, szAppend, ARRAYSIZE(szAppend)) != 0) { StringCchCat(szTemp, ARRAYSIZE(szTemp), szAppend); // display string, truncation ok } } else { LoadString(HINST_THISDLL, c_aIconRegKeys[nIndex].iDefaultTitleResource, szTemp, ARRAYSIZE(szTemp)); } lvI.iItem = nIndex; lvI.iSubItem = 0; lvI.pszText = szTemp; lvI.iImage = nIndex; if(ListView_InsertItem(_hWndList, &lvI) == -1) return NULL; } #ifdef JIGGLE_FIX // To fix long standing listview bug, we need to "jiggle" the listview // window size so that it will do a recompute and realize that we need a // scroll bar... GetWindowRect(_hWndList, &rc); MapWindowPoints( NULL, hWndParent, (LPPOINT)&rc, 2 ); MoveWindow(_hWndList, rc.left, rc.top, rc.right - rc.left+1, rc.bottom - rc.top, FALSE ); MoveWindow(_hWndList, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, FALSE ); #endif // Set First item to selected ListView_SetItemState (_hWndList, 0, LVIS_SELECTED, LVIS_SELECTED); // Get Selected item for (m_nIndex = 0; m_nIndex < ARRAYSIZE(c_aIconRegKeys); m_nIndex++) { if (ListView_GetItemState(_hWndList, m_nIndex, LVIS_SELECTED)) { bEnable = TRUE; break; } } if (m_nIndex >= ARRAYSIZE(c_aIconRegKeys)) { m_nIndex = -1; } EnableWindow(GetDlgItem(hWndParent, IDC_CHANGEICON2), bEnable); EnableWindow(GetDlgItem(hWndParent, IDC_ICONDEFAULT), bEnable); return _hWndList; } #define CUSTOMIZE_DLGPROC 1 #define CUSTOMIZE_WEB_DLGPROC 2 void CCompPropSheetPage::_OnInitDialog(HWND hwnd, INT iPage) { if (FAILED(GetActiveDesktop(&g_pActiveDeskAdv))) { return; } switch (iPage) { case CUSTOMIZE_DLGPROC : { // // Read in the restrictions. // // Init the Icon UI // Create our list view and fill it with the system icons m_nIndex = 0; _CreateListView(hwnd); _OnInitDesktopOptionsUI(hwnd); // // Enable the Desktop Cleanup Wizard if we are on the right version // of the OS and the DesktopCleanup NoRun policy is not set // // BOOL fCleanupEnabled = (IsOS(OS_PERSONAL) || IsOS(OS_PROFESSIONAL)) && !IsUserAGuest() && !SHRestricted(REST_NODESKTOPCLEANUP); if (fCleanupEnabled) { if (BST_INDETERMINATE == g_iRunDesktopCleanup) { DWORD dwData = 0; DWORD dwType; DWORD cch = sizeof (DWORD); if (ERROR_SUCCESS == SHRegGetUSValue(REGSTR_DESKTOP_CLEANUP,REGSTR_VAL_DONTRUN, &dwType, &dwData, &cch, FALSE, NULL, 0) && dwData != 0) { g_iRunDesktopCleanup = BST_UNCHECKED; } else { g_iRunDesktopCleanup = BST_CHECKED; } } CheckDlgButton(hwnd, IDC_DESKCLNR_CHECK, g_iRunDesktopCleanup); } else { ShowWindow(GetDlgItem(hwnd, IDC_COMP_CLEANUP_GROUP), FALSE); ShowWindow(GetDlgItem(hwnd, IDC_DESKCLNR_MOVEUNUSED), FALSE); ShowWindow(GetDlgItem(hwnd, IDC_DESKCLNR_CHECK), FALSE); ShowWindow(GetDlgItem(hwnd, IDC_DESKCLNR_RUNWIZARD), FALSE); } } break; case CUSTOMIZE_WEB_DLGPROC: { _fLaunchGallery = FALSE; _fAllowAdd = !SHRestricted(REST_NOADDDESKCOMP); _fAllowDel = !SHRestricted(REST_NODELDESKCOMP); _fAllowEdit = !SHRestricted(REST_NOEDITDESKCOMP); _fAllowClose = !SHRestricted(REST_NOCLOSEDESKCOMP); _fAllowReset = _fAllowAdd && _fAllowDel && _fAllowEdit && _fAllowClose && !SHRestricted(REST_NOCHANGINGWALLPAPER); _fForceAD = SHRestricted(REST_FORCEACTIVEDESKTOPON); _hwndLV = GetDlgItem(hwnd, IDC_COMP_LIST); EnableWindow(GetDlgItem(hwnd, IDC_COMP_NEW), _fAllowAdd); EnableWindow(GetDlgItem(hwnd, IDC_COMP_DELETE), _fAllowDel); EnableWindow(GetDlgItem(hwnd, IDC_COMP_PROPERTIES), _fAllowEdit); EnableWindow(GetDlgItem(hwnd, IDC_COMP_SYNCHRONIZE), _fAllowEdit); if (_fAllowClose) { ListView_SetExtendedListViewStyle(_hwndLV, LVS_EX_CHECKBOXES); } // // Add the single column that we want. // LV_COLUMN lvc; lvc.mask = LVCF_FMT | LVCF_SUBITEM; lvc.fmt = LVCFMT_LEFT; lvc.iSubItem = 0; ListView_InsertColumn(_hwndLV, 0, &lvc); // // Now make the UI match the g_pActiveDeskAdv object. // _SetUIFromDeskState(FALSE); // // Select the first item, if it exists. // int cComp; g_pActiveDeskAdv->GetDesktopItemCount(&cComp, 0); if (cComp) { ListView_SetItemState(_hwndLV, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); } _EnableControls(hwnd); } break; } } HRESULT CCompPropSheetPage::_OnInitDesktopOptionsUI(HWND hwnd) { SHELLSTATE ss = {0}; SHGetSetSettings(&ss, SSF_STARTPANELON, FALSE); //See if the StartPanel is on! _iStartPanelOn = ss.fStartPanelOn ? 1 : 0; //Remember this in the class! // Check or uncheck the various icons based on whether they are on/off now. _UpdateDesktopIconsUI(hwnd); return S_OK; } HRESULT CCompPropSheetPage::_UpdateDesktopIconsUI(HWND hwnd) { // Check or uncheck the various icons based on whether they are on/off now. for (int iIndex = 0; iIndex < NUM_DESKICONS; iIndex++) { // If HideDeskIcon[][] is true, uncheck the checkbox! If it is FALSE, check the checkbox. CheckDlgButton(hwnd, c_aDeskIconId[iIndex].iDeskIconDlgItemId, !_afHideIcon[_iStartPanelOn][iIndex]); // If the policy is set, disable this CheckBox! EnableWindow(GetDlgItem(hwnd, c_aDeskIconId[iIndex].iDeskIconDlgItemId), !_afDisableCheckBox[iIndex]); } return S_OK; } void CCompPropSheetPage::_OnNotify(HWND hwnd, WPARAM wParam, LPNMHDR lpnm) { switch (wParam) { case IDC_COMP_DESKTOPWEBPAGES_CHECK: _fLockDesktopItems = IsDlgButtonChecked(hwnd, IDC_COMP_DESKTOPWEBPAGES_CHECK); break; case IDC_DESKTOP_ICONS: { switch (lpnm->code) case LVN_ITEMCHANGED: { BOOL fSomethingSelected = FALSE; // Find out who's selected now for( m_nIndex = 0; m_nIndex < ARRAYSIZE(c_aIconRegKeys); m_nIndex++) { if( ListView_GetItemState(_hWndList, m_nIndex, LVIS_SELECTED)) { fSomethingSelected = TRUE; break; } } if (m_nIndex >= ARRAYSIZE(c_aIconRegKeys)) { m_nIndex = -1; } EnableWindow(GetDlgItem(hwnd, IDC_CHANGEICON2), fSomethingSelected); EnableWindow(GetDlgItem(hwnd, IDC_ICONDEFAULT), fSomethingSelected); } } break; case IDC_COMP_LIST: { switch (lpnm->code) { case LVN_ITEMCHANGED: NM_LISTVIEW *pnmlv = (NM_LISTVIEW *)lpnm; if ((pnmlv->uChanged & LVIF_STATE) && ((pnmlv->uNewState ^ pnmlv->uOldState) & COMP_CHECKED)) { LV_ITEM lvi = {0}; lvi.iItem = pnmlv->iItem; lvi.mask = LVIF_PARAM; ListView_GetItem(_hwndLV, &lvi); COMPONENT comp; comp.dwSize = sizeof(COMPONENT); if (SUCCEEDED(g_pActiveDeskAdv->GetDesktopItemByID(lvi.lParam, &comp, 0))) { comp.fChecked = (pnmlv->uNewState & COMP_CHECKED) != 0; g_pActiveDeskAdv->ModifyDesktopItem(&comp, COMP_ELEM_CHECKED); } if (_fInitialized) { g_fDirtyAdvanced = TRUE; } } if ((pnmlv->uChanged & LVIF_STATE) && ((pnmlv->uNewState ^ pnmlv->uOldState) & LVIS_SELECTED)) { _EnableControls(hwnd); // toggle delete, properties } break; } } break; default: { switch (lpnm->code) { case PSN_APPLY: { // store desktop flags DWORD dwFlags, dwFlagsPrev; dwFlags = dwFlagsPrev = GetDesktopFlags(); if (_fLockDesktopItems) { dwFlags |= COMPONENTS_LOCKED; } else { dwFlags &= ~COMPONENTS_LOCKED; } if (dwFlags != dwFlagsPrev) { g_fDirtyAdvanced = TRUE; SetDesktopFlags(COMPONENTS_LOCKED, dwFlags); } _fCustomizeDesktopOK = TRUE; } break; } } break; } } // // Returns TRUE if the string looks like a candidate for // getting qualified as "file:". // BOOL LooksLikeFile(LPCTSTR psz) { BOOL fRet = FALSE; if (psz[0] && psz[1] && #ifndef UNICODE !IsDBCSLeadByte(psz[0]) && !IsDBCSLeadByte(psz[1]) && #endif ((psz[0] == TEXT('\\')) || (psz[1] == TEXT(':')) || (psz[1] == TEXT('|')))) { fRet = TRUE; } return fRet; } #define GOTO_GALLERY (-2) BOOL_PTR CALLBACK AddComponentDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { LPTSTR pszSource = (LPTSTR)GetWindowLongPtr(hdlg, DWLP_USER); TCHAR szBuf[INTERNET_MAX_URL_LENGTH]; switch (uMsg) { case WM_INITDIALOG: pszSource = (LPTSTR)lParam; SetWindowLongPtr(hdlg, DWLP_USER, (LONG_PTR)pszSource); SetDlgItemText(hdlg, IDC_CPROP_SOURCE, c_szNULL); EnableWindow(GetDlgItem(hdlg, IDOK), FALSE); SHAutoComplete(GetDlgItem(hdlg, IDC_CPROP_SOURCE), 0); return TRUE; case WM_COMMAND: switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDC_CPROP_BROWSE: { GetDlgItemText(hdlg, IDC_CPROP_SOURCE, szBuf, ARRAYSIZE(szBuf)); if (!LooksLikeFile(szBuf)) { // // Open the favorites folder when we aren't // looking at a specific file. // SHGetSpecialFolderPath(hdlg, szBuf, CSIDL_FAVORITES, FALSE); // // Append a slash because GetFileName breaks the // string into a file & dir, and we want to make sure // the entire favorites path is treated as a dir. // PathAddBackslash(szBuf); } else { PathRemoveArgs(szBuf); } DWORD adwFlags[] = { GFN_ALL, GFN_PICTURE, (GFN_LOCALHTM | GFN_LOCALMHTML | GFN_CDF | GFN_URL), 0 }; int aiTypes[] = { IDS_COMP_FILETYPES, IDS_ALL_PICTURES, IDS_ALL_HTML, 0 }; if (GetFileName(hdlg, szBuf, ARRAYSIZE(szBuf), aiTypes, adwFlags) && CheckAndResolveLocalUrlFile(szBuf, ARRAYSIZE(szBuf))) { SetDlgItemText(hdlg, IDC_CPROP_SOURCE, szBuf); } } break; case IDC_CPROP_SOURCE: if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE) { EnableWindow(GetDlgItem(hdlg, IDOK), GetWindowTextLength(GetDlgItem(hdlg, IDC_CPROP_SOURCE)) > 0); } break; case IDOK: GetDlgItemText(hdlg, IDC_CPROP_SOURCE, pszSource, INTERNET_MAX_URL_LENGTH); ASSERT(pszSource[0]); if (ValidateFileName(hdlg, pszSource, IDS_COMP_TYPE1) && CheckAndResolveLocalUrlFile(pszSource, INTERNET_MAX_URL_LENGTH)) { // // Qualify non file-protocol strings. // if (!LooksLikeFile(pszSource)) { DWORD cchSize = INTERNET_MAX_URL_LENGTH; PathRemoveBlanks(pszSource); ParseURLFromOutsideSource(pszSource, pszSource, &cchSize, NULL); } EndDialog(hdlg, 0); } break; case IDCANCEL: EndDialog(hdlg, -1); break; case IDC_GOTO_GALLERY: EndDialog(hdlg, GOTO_GALLERY); break; } break; } return FALSE; } BOOL IsUrlPicture(LPCTSTR pszUrl) { BOOL fRet = FALSE; if(pszUrl[0] == TEXT('\0')) { fRet = TRUE; } else { LPTSTR pszExt = PathFindExtension(pszUrl); if ((lstrcmpi(pszExt, TEXT(".BMP")) == 0) || (StrCmpIC(pszExt, TEXT(".GIF")) == 0) || // 368690: Strange, but we must compare 'i' in both caps and lower case. (lstrcmpi(pszExt, TEXT(".JPG")) == 0) || (lstrcmpi(pszExt, TEXT(".JPE")) == 0) || (lstrcmpi(pszExt, TEXT(".JPEG")) == 0) || (lstrcmpi(pszExt, TEXT(".DIB")) == 0) || (lstrcmpi(pszExt, TEXT(".PNG")) == 0)) { fRet = TRUE; } } return(fRet); } int GetComponentType(LPCTSTR pszUrl) { return IsUrlPicture(pszUrl) ? COMP_TYPE_PICTURE : COMP_TYPE_WEBSITE; } void CreateComponent(COMPONENTA *pcomp, LPCTSTR pszUrl) { pcomp->dwSize = sizeof(*pcomp); pcomp->dwID = (DWORD)-1; pcomp->iComponentType = GetComponentType(pszUrl); pcomp->fChecked = TRUE; pcomp->fDirty = FALSE; pcomp->fNoScroll = FALSE; pcomp->cpPos.dwSize = sizeof(pcomp->cpPos); pcomp->cpPos.iLeft = COMPONENT_DEFAULT_LEFT; pcomp->cpPos.iTop = COMPONENT_DEFAULT_TOP; pcomp->cpPos.dwWidth = COMPONENT_DEFAULT_WIDTH; pcomp->cpPos.dwHeight = COMPONENT_DEFAULT_HEIGHT; pcomp->cpPos.izIndex = COMPONENT_TOP; pcomp->cpPos.fCanResize = TRUE; pcomp->cpPos.fCanResizeX = pcomp->cpPos.fCanResizeY = TRUE; pcomp->cpPos.iPreferredLeftPercent = pcomp->cpPos.iPreferredTopPercent = 0; if (FAILED(StringCchCopy(pcomp->szSource, ARRAYSIZE(pcomp->szSource), pszUrl))) { pcomp->szSource[0] = TEXT('\0'); } if (FAILED(StringCchCopy(pcomp->szSubscribedURL, ARRAYSIZE(pcomp->szSubscribedURL), pszUrl))) { pcomp->szSubscribedURL[0] = TEXT('\0'); } pcomp->szFriendlyName[0] = TEXT('\0'); } BOOL FindComponent(IN LPCTSTR pszUrl, IN IActiveDesktop * pActiveDesktop) { BOOL fRet = FALSE; int i, ccomp; LPWSTR pwszUrl; #ifndef UNICODE WCHAR wszUrl[INTERNET_MAX_URL_LENGTH]; SHAnsiToUnicode(pszUrl, wszUrl, ARRAYSIZE(wszUrl)); pwszUrl = wszUrl; #else pwszUrl = (LPWSTR)pszUrl; #endif if (pActiveDesktop) { pActiveDesktop->GetDesktopItemCount(&ccomp, 0); for (i=0; iGetDesktopItem(i, &comp, 0))) { if (StrCmpIW(pwszUrl, comp.wszSource) == 0) { fRet = TRUE; break; } } } } return fRet; } void EmptyListview(IActiveDesktop * pActiveDesktop, HWND hwndLV) { // // Delete all the old components. // int cComp; pActiveDesktop->GetDesktopItemCount(&cComp, 0); int i; COMPONENT comp; comp.dwSize = sizeof(COMPONENT); for (i=0; iGetDesktopItemCount(&cComp, 0); for (int i=0; iGetDesktopItem(i, &comp, 0))) { if (StrCmpW(pwszUrl, comp.wszSource) == 0) { break; } } } // // Find the matching listview entry (search for dwID). // if (i != cComp) { int nItems = ListView_GetItemCount(_hwndLV); for (i=0; idwSize = sizeof(comp); pcomp->dwCurItemState = IS_NORMAL; } if (iChoice == GOTO_GALLERY) // the user wants to launch the gallery { if (!fDeferGallery) { WCHAR szGalleryUrl[INTERNET_MAX_URL_LENGTH]; if (SUCCEEDED(URLSubLoadString(HINST_THISDLL, IDS_VISIT_URL, szGalleryUrl, ARRAYSIZE(szGalleryUrl), URLSUB_ALL))) { NavToUrlUsingIEW(szGalleryUrl, TRUE); } } } else if (iChoice >= 0) { // the user has entered a URL address WCHAR szSourceW[INTERNET_MAX_URL_LENGTH]; SHTCharToUnicode(szSource, szSourceW, ARRAYSIZE(szSourceW)); if (!SUCCEEDED(pad->AddUrl(hwndOwner, szSourceW, pcomp, 0))) iChoice = -1; } SHCoUninitialize(hrInit); return iChoice; } void CCompPropSheetPage::_NewComponent(HWND hwnd) { COMPONENT comp; comp.dwSize = sizeof(comp); comp.dwCurItemState = IS_NORMAL; INT_PTR iChoice = NewComponent(hwnd, g_pActiveDeskAdv, TRUE, &comp); if (iChoice == GOTO_GALLERY) // the user wants to launch the gallery { _fLaunchGallery = TRUE; g_fLaunchGallery = TRUE; g_fDirtyAdvanced = TRUE; PropSheet_PressButton(GetParent(hwnd), PSBTN_OK); } else { if (iChoice >= 0) // the user has entered a URL address { // Add component to listview. // // Need to reload the entire listview so that it is shown in // the correct zorder. _SetUIFromDeskState(TRUE); // Select the newly added component. _SelectComponent(comp.wszSource); } g_fDirtyAdvanced = TRUE; } } void CCompPropSheetPage::_EditComponent(HWND hwnd) { int iIndex = ListView_GetNextItem(_hwndLV, -1, LVNI_SELECTED); if (iIndex > -1) { LV_ITEM lvi = {0}; lvi.mask = LVIF_PARAM; lvi.iItem = iIndex; ListView_GetItem(_hwndLV, &lvi); COMPONENT comp = { sizeof(comp) }; if (SUCCEEDED(g_pActiveDeskAdv->GetDesktopItemByID(lvi.lParam, &comp, 0))) { LPTSTR pszSubscribedURL; #ifndef UNICODE TCHAR szSubscribedURL[INTERNET_MAX_URL_LENGTH]; SHUnicodeToAnsi(comp.wszSubscribedURL, szSubscribedURL, ARRAYSIZE(szSubscribedURL)); pszSubscribedURL = szSubscribedURL; #else pszSubscribedURL = (LPTSTR)comp.wszSubscribedURL; #endif if (SUCCEEDED(ShowSubscriptionProperties(pszSubscribedURL, hwnd))) { g_fDirtyAdvanced = TRUE; } } } } void CCompPropSheetPage::_DeleteComponent(HWND hwnd) { int iIndex = ListView_GetNextItem(_hwndLV, -1, LVNI_ALL | LVNI_SELECTED); if (iIndex > -1) { LV_ITEM lvi = {0}; lvi.mask = LVIF_PARAM; lvi.iItem = iIndex; ListView_GetItem(_hwndLV, &lvi); COMPONENT comp; comp.dwSize = sizeof(COMPONENT); if (SUCCEEDED(g_pActiveDeskAdv->GetDesktopItemByID(lvi.lParam, &comp, 0))) { TCHAR szMsg[1024]; TCHAR szTitle[MAX_PATH]; LoadString(HINST_THISDLL, IDS_COMP_CONFIRMDEL, szMsg, ARRAYSIZE(szMsg)); LoadString(HINST_THISDLL, IDS_COMP_TITLE, szTitle, ARRAYSIZE(szTitle)); if (MessageBox(hwnd, szMsg, szTitle, MB_YESNO | MB_ICONQUESTION) == IDYES) { g_pActiveDeskAdv->RemoveDesktopItem(&comp, 0); ListView_DeleteItem(_hwndLV, iIndex); int cComp = ListView_GetItemCount(_hwndLV); if (cComp == 0) { SendMessage(hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDC_COMP_NEW), TRUE); } else { int iSel = (iIndex > cComp - 1 ? cComp - 1 : iIndex); ListView_SetItemState(_hwndLV, iSel, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); } LPTSTR pszSubscribedURL; #ifndef UNICODE TCHAR szSubscribedURL[INTERNET_MAX_URL_LENGTH]; SHUnicodeToAnsi(comp.wszSubscribedURL, szSubscribedURL, ARRAYSIZE(szSubscribedURL)); pszSubscribedURL = szSubscribedURL; #else pszSubscribedURL = comp.wszSubscribedURL; #endif DeleteFromSubscriptionList(pszSubscribedURL); } g_fDirtyAdvanced = TRUE; } } } // // Desktop Cleanup stuff // STDAPI ApplyDesktopCleanupSettings() { // set the registry value DWORD dwData = (BST_CHECKED == g_iRunDesktopCleanup) ? 0 : 1; SHRegSetUSValue(REGSTR_DESKTOP_CLEANUP, REGSTR_VAL_DONTRUN, REG_DWORD, &dwData, sizeof(dwData), SHREGSET_FORCE_HKCU); return S_OK; } void CCompPropSheetPage::_DesktopCleaner(HWND hwnd) { TCHAR szRunDLL[MAX_PATH]; if (GetSystemDirectory(szRunDLL, ARRAYSIZE(szRunDLL)) && PathAppend(szRunDLL, TEXT("rundll32.exe"))) { SHELLEXECUTEINFO sei = {0}; sei.cbSize = sizeof(sei); sei.hwnd = hwnd; sei.lpFile = szRunDLL; sei.lpParameters = TEXT("fldrclnr.dll,Wizard_RunDLL all"); sei.nShow = SW_SHOWNORMAL; ShellExecuteEx(&sei); } } void CCompPropSheetPage::_SynchronizeAllComponents(IActiveDesktop *pActDesktop) { IADesktopP2* padp2; if (SUCCEEDED(pActDesktop->QueryInterface(IID_PPV_ARG(IADesktopP2, &padp2)))) { padp2->UpdateAllDesktopSubscriptions(); padp2->Release(); } } void CCompPropSheetPage::_OnCommand(HWND hwnd, WORD wNotifyCode, WORD wID, HWND hwndCtl) { BOOL fFocusToList = FALSE; switch (wID) { case IDC_COMP_NEW: _NewComponent(hwnd); // 98/08/19 vtan #152418: Set the default border to "New". This // will be changed when the focus is changed to the component list // but this allows the dialog handling code to draw the default // border correctly. (BOOL)SendMessage(hwnd, WM_NEXTDLGCTL, reinterpret_cast(GetDlgItem(hwnd, IDC_COMP_NEW)), static_cast(TRUE)); fFocusToList = TRUE; break; case IDC_COMP_PROPERTIES: _EditComponent(hwnd); // 98/08/19 vtan #152418: Same as above. (BOOL)SendMessage(hwnd, WM_NEXTDLGCTL, reinterpret_cast(GetDlgItem(hwnd, IDC_COMP_PROPERTIES)), static_cast(TRUE)); fFocusToList = TRUE; break; case IDC_COMP_DELETE: _DeleteComponent(hwnd); // 98/08/19 vtan #152418: Same as above. (BOOL)SendMessage(hwnd, WM_NEXTDLGCTL, reinterpret_cast(GetDlgItem(hwnd, IDC_COMP_DELETE)), static_cast(TRUE)); fFocusToList = TRUE; break; case IDC_DESKCLNR_RUNWIZARD: _DesktopCleaner(hwnd); break; case IDC_DESKCLNR_CHECK: // if the button is clicked, update the global { int iButState = IsDlgButtonChecked(hwnd, IDC_DESKCLNR_CHECK); if (iButState != g_iRunDesktopCleanup) { ASSERT(iButState != BST_INDETERMINATE); g_iRunDesktopCleanup = iButState; g_fDirtyAdvanced = TRUE; } } break; case IDC_COMP_SYNCHRONIZE: _SynchronizeAllComponents(g_pActiveDeskAdv); break; case IDC_CHANGEICON2: if (-1 != m_nIndex) { WCHAR szExp[MAX_PATH]; INT i = _IconData[m_nIndex].iOldIndex; ExpandEnvironmentStringsW(_IconData[m_nIndex].szOldFile, szExp, ARRAYSIZE(szExp)); if (PickIconDlg(hwnd, szExp, ARRAYSIZE(szExp), &i) == TRUE) { HICON hIcon; if (SUCCEEDED(StringCchCopy(_IconData[m_nIndex].szNewFile, ARRAYSIZE(_IconData[m_nIndex].szNewFile), szExp))) { _IconData[m_nIndex].iNewIndex = i; if (SUCCEEDED(ExtractPlusColorIcon(_IconData[m_nIndex].szNewFile, _IconData[m_nIndex].iNewIndex, &hIcon, 0, 0))) { ImageList_ReplaceIcon(_hIconList, m_nIndex, hIcon); ListView_RedrawItems(_hWndList, m_nIndex, m_nIndex); } } } SetFocus(_hWndList); } break; case IDC_ICONDEFAULT: if (-1 != m_nIndex) { TCHAR szPath[MAX_PATH]; HICON hIcon; if (!ExpandEnvironmentStrings(c_aIconRegKeys[m_nIndex].pszDefault, szPath, ARRAYSIZE(szPath)) || FAILED(StringCchCopy(szPath, ARRAYSIZE(szPath), c_aIconRegKeys[m_nIndex].pszDefault))) { break; } if (SUCCEEDED(StringCchCopy(_IconData[m_nIndex].szNewFile, ARRAYSIZE(_IconData[m_nIndex].szNewFile), szPath))) { _IconData[m_nIndex].iNewIndex = c_aIconRegKeys[m_nIndex].nDefaultIndex; ExtractPlusColorIcon(_IconData[m_nIndex].szNewFile, _IconData[m_nIndex].iNewIndex, &hIcon, 0, 0); ImageList_ReplaceIcon(_hIconList, m_nIndex, hIcon); ListView_RedrawItems(_hWndList, m_nIndex, m_nIndex); SetFocus(_hWndList); } } break; case IDC_DESKTOP_ICON_MYDOCS: case IDC_DESKTOP_ICON_MYCOMP: case IDC_DESKTOP_ICON_MYNET: case IDC_DESKTOP_ICON_IE: { //Get the current button state and save it. BOOL fOriginalBtnState = IsDlgButtonChecked(hwnd, wID); //Toggle the button from checked to unchecked (or vice-versa). CheckDlgButton(hwnd, wID, (fOriginalBtnState ? BST_UNCHECKED : BST_CHECKED)); for(int iIndex = 0; iIndex < NUM_DESKICONS; iIndex++) { if(wID == c_aDeskIconId[iIndex].iDeskIconDlgItemId) { // Note#1: The inverse logic is used below. If the originally button is checked, // it means that now it is unchecked, which means that icon should now be hidden; // (i.e) the HideDeskIcon[][] should be set to TRUE. // // Note#2: When the end-user toggles these, we want to set the same setting for // both the modes now! _afHideIcon[0][iIndex] = _afHideIcon[1][iIndex] = fOriginalBtnState; } } } break; } //Set the focus back to the components list, if necessary if (fFocusToList) { int iIndex = ListView_GetNextItem(_hwndLV, -1, LVNI_SELECTED); if (iIndex > -1) { SetFocus(GetDlgItem(hwnd, IDC_COMP_LIST)); } } } void CCompPropSheetPage::_OnDestroy(INT iPage) { if (CUSTOMIZE_DLGPROC == iPage) { ReleaseActiveDesktop(&g_pActiveDeskAdv); if (_fLaunchGallery) { WCHAR szGalleryUrl[INTERNET_MAX_URL_LENGTH]; if (SUCCEEDED(URLSubLoadString(HINST_THISDLL, IDS_VISIT_URL, szGalleryUrl, ARRAYSIZE(szGalleryUrl), URLSUB_ALL))) { NavToUrlUsingIEW(szGalleryUrl, TRUE); } } } } void CCompPropSheetPage::_OnGetCurSel(int *piIndex) { if (_hwndLV) { *piIndex = ListView_GetNextItem(_hwndLV, -1, LVNI_ALL | LVNI_SELECTED); } else { *piIndex = -1; } } INT_PTR CCompPropSheetPage::_CustomizeDlgProcHelper(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam, INT iPage) { CCompPropSheetPage * pThis; if (WM_INITDIALOG == wMsg) { pThis = (CCompPropSheetPage *) ((PROPSHEETPAGE*)lParam)->lParam; if (pThis) { SetWindowLongPtr(hDlg, DWLP_USER, (LPARAM) pThis); } } else { pThis = (CCompPropSheetPage *)GetWindowLongPtr(hDlg, DWLP_USER); } if (pThis) return pThis->_CustomizeDlgProc(hDlg, wMsg, wParam, lParam, iPage); return DefWindowProc(hDlg, wMsg, wParam, lParam); } INT_PTR CALLBACK CCompPropSheetPage::CustomizeDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { return _CustomizeDlgProcHelper(hDlg, wMsg, wParam, lParam, CUSTOMIZE_DLGPROC); } INT_PTR CALLBACK CCompPropSheetPage::WebDlgProc(HWND hDlg, UINT wMsg, WPARAM wParam, LPARAM lParam) { return _CustomizeDlgProcHelper(hDlg, wMsg, wParam, lParam, CUSTOMIZE_WEB_DLGPROC); } BOOL_PTR CCompPropSheetPage::_CustomizeDlgProc(HWND hdlg, UINT uMsg, WPARAM wParam, LPARAM lParam, INT iPage) { switch(uMsg) { case WM_INITDIALOG: _OnInitDialog(hdlg, iPage); break; case WM_NOTIFY: _OnNotify(hdlg, wParam, (LPNMHDR)lParam); break; case WM_COMMAND: _OnCommand(hdlg, HIWORD(wParam), LOWORD(wParam), (HWND)lParam); break; case WM_SETTINGCHANGE: //Check if this is a shell StateChange? if(lstrcmpi((LPTSTR)(lParam), TEXT("ShellState")) == 0) { //Check if the StartPanel on/off state has changed. SHELLSTATE ss = {0}; SHGetSetSettings(&ss, SSF_STARTPANELON, FALSE); //See if the StartPanel is on! //See if the StartPanel on/off state has changed if(BOOLIFY(ss.fStartPanelOn) != BOOLIFY((BOOL)_iStartPanelOn)) { _iStartPanelOn = (ss.fStartPanelOn ? 1 : 0); //Save the new state. //Refresh the UI based on the new state. _UpdateDesktopIconsUI(hdlg); } } // Intentional fallthrough.... case WM_SYSCOLORCHANGE: case WM_DISPLAYCHANGE: SHPropagateMessage(hdlg, uMsg, wParam, lParam, TRUE); break; case WM_DESTROY: _OnDestroy(iPage); break; case WM_COMP_GETCURSEL: _OnGetCurSel((int *)lParam); break; case WM_HELP: WinHelp((HWND)((LPHELPINFO) lParam)->hItemHandle, SZ_HELPFILE_DESKTOPITEMS, HELP_WM_HELP, (ULONG_PTR)(void *)aDesktopItemsHelpIDs); break; case WM_CONTEXTMENU: WinHelp((HWND) wParam, SZ_HELPFILE_DESKTOPITEMS, HELP_CONTEXTMENU, (ULONG_PTR)(void *) aDesktopItemsHelpIDs); break; } return FALSE; } HRESULT CCompPropSheetPage::_IsDirty(IN BOOL * pIsDirty) { HRESULT hr = E_INVALIDARG; if (pIsDirty) { *pIsDirty = g_fDirtyAdvanced; if (!*pIsDirty) { // Check if any of the icons have changed. for (int nIndex = 0; nIndex < ARRAYSIZE(_IconData); nIndex++) { if ((_IconData[nIndex].iNewIndex != _IconData[nIndex].iOldIndex) || (StrCmpI(_IconData[nIndex].szNewFile, _IconData[nIndex].szOldFile))) { *pIsDirty = TRUE; break; } } } hr = S_OK; } return hr; } HRESULT CCompPropSheetPage::DisplayAdvancedDialog(IN HWND hwndParent, IN IPropertyBag * pAdvPage, IN BOOL * pfEnableApply) { HRESULT hr = S_OK; // Load State Into Advanced Dialog *pfEnableApply = FALSE; GetActiveDesktop(&g_pActiveDesk); GetActiveDesktop(&g_pActiveDeskAdv); ActiveDesktop_CopyState(g_pActiveDesk, g_pActiveDeskAdv); hr = _LoadIconState(pAdvPage); if (SUCCEEDED(hr)) { hr = _LoadDeskIconState(pAdvPage); if (SUCCEEDED(hr)) { int iNumberOfPages = 2; PROPSHEETPAGE psp = {0}; psp.dwSize = sizeof(psp); psp.hInstance = HINST_THISDLL; psp.dwFlags = PSP_DEFAULT; psp.lParam = (LPARAM) this; psp.pszTemplate = MAKEINTRESOURCE(IDD_CUSTOMIZE); psp.pfnDlgProc = CCompPropSheetPage::CustomizeDlgProc; HPROPSHEETPAGE rghpsp[2]; rghpsp[0] = CreatePropertySheetPage(&psp); // Any of the following policies can disable the Web tab. // 1. If no active desktop policy set, don't put up the property page // 2. If policy is set to lock down active desktop, don't put up the // property page // 3. If policy is set to not allow components, don't put up the // property page if (((!SHRestricted(REST_FORCEACTIVEDESKTOPON)) && PolicyNoActiveDesktop()) || // 1. (SHRestricted(REST_NOACTIVEDESKTOPCHANGES)) || // 2. (SHRestricted(REST_NODESKCOMP)) || // 3. (SHRestricted(REST_CLASSICSHELL))) // 4 { // It's restricted, so don't add Web page. iNumberOfPages = 1; //"General" page is the only page in this property sheet! } else { // No active desktop restriction! Go ahead and add the "Web" tab! psp.pszTemplate = MAKEINTRESOURCE(IDD_CUSTOMIZE_WEB); psp.pfnDlgProc = CCompPropSheetPage::WebDlgProc; rghpsp[1] = CreatePropertySheetPage(&psp); iNumberOfPages = 2; //"General" and "Web" are the two pages in this Property sheet! } PROPSHEETHEADER psh = {0}; psh.dwSize = sizeof(psh); psh.dwFlags = PSH_NOAPPLYNOW; psh.hwndParent = hwndParent; psh.hInstance = HINST_THISDLL; TCHAR szTitle[MAX_PATH]; LoadString(HINST_THISDLL, IDS_PROPSHEET_TITLE, szTitle, ARRAYSIZE(szTitle)); psh.pszCaption = szTitle; psh.nPages = iNumberOfPages; psh.phpage = rghpsp; _fCustomizeDesktopOK = FALSE; PropertySheet(&psh); if (_fCustomizeDesktopOK) { // The user clicked OK, so merge modified state back into base dialog _IsDirty(pfEnableApply); // The user clicked Okay in the dialog so merge the dirty state from the // advanced dialog into the base dialog. MergeState(); _MergeIconState(pAdvPage); _MergeDeskIconState(pAdvPage); } // If the user selected to open the component gallery in Web->New, then // we want to close both the Advanced dlg and the base Dlg with "OK". // This way we persist the changes they have made so far, and then the web // page will allow them to add more. if (TRUE == g_fLaunchGallery) { IThemeUIPages * pThemeUIPages; HWND hwndBasePropDlg = GetParent(hwndParent); PropSheet_PressButton(hwndBasePropDlg, PSBTN_OK); hr = IUnknown_GetSite(pAdvPage, IID_PPV_ARG(IThemeUIPages, &pThemeUIPages)); if (SUCCEEDED(hr)) { // We now want to tell the base dialog to close too. hr = pThemeUIPages->ApplyPressed(TUIAP_CLOSE_DIALOG); pThemeUIPages->Release(); } } } } ReleaseActiveDesktop(&g_pActiveDesk); ReleaseActiveDesktop(&g_pActiveDeskAdv); return hr; } ULONG CCompPropSheetPage::AddRef() { _cRef++; return _cRef; } ULONG CCompPropSheetPage::Release() { ASSERT(_cRef > 0); _cRef--; if (_cRef > 0) return _cRef; delete this; return 0; } HRESULT CCompPropSheetPage::QueryInterface(REFIID riid, void **ppvObj) { HRESULT hr = E_NOINTERFACE; static const QITAB qit[] = { QITABENT(CCompPropSheetPage, IObjectWithSite), QITABENT(CCompPropSheetPage, IAdvancedDialog), { 0 }, }; return QISearch(this, qit, riid, ppvObj); } CCompPropSheetPage::CCompPropSheetPage() : _iPreviousSelection(-1), _cRef(1) { _fInitialized = FALSE; _fLaunchGallery = FALSE; _punkSite = NULL; _hWndList = NULL; _hIconList = NULL; _fLockDesktopItems = GetDesktopFlags() & COMPONENTS_LOCKED; // We don't need to do any work here but it's a good cue to // reset our state because the Advance dialog is opening. g_fDirtyAdvanced = FALSE; // The advanced page isn't dirty yet. g_fLaunchGallery = FALSE; // Will be true if they launch the gallery. RegisterCompPreviewClass(); } CCompPropSheetPage::~CCompPropSheetPage() { } // // The following function updates the registry such that the given icon can be hidden or shown // on the desktop. // This function is called from RegFldr.cpp to selectively hide RegItems like MyComputer, // RecycleBin, MyDocuments and MyNetplaces Icons. // HRESULT ShowHideIconOnlyOnDesktop(const CLSID *pclsid, int StartIndex, int EndIndex, BOOL fHide) { HRESULT hr = S_OK; int iStartPanel; TCHAR szRegPath[MAX_PATH]; TCHAR szValueName[MAX_GUID_STRING_LEN]; SHStringFromGUID(*pclsid, szValueName, ARRAYSIZE(szValueName)); // i = 0 is for StartPanel off and i = 1 is for StartPanel ON! for(iStartPanel = StartIndex; SUCCEEDED(hr) && iStartPanel <= EndIndex; iStartPanel++) { //Get the proper registry path based on if StartPanel is ON/OFF hr = StringCchPrintf(szRegPath, ARRAYSIZE(szRegPath), REGSTR_PATH_HIDDEN_DESKTOP_ICONS, c_apstrRegLocation[iStartPanel]); if (SUCCEEDED(hr)) { //Write the setting to the registry! DWORD dwHide = (DWORD)fHide; LONG lRet = SHRegSetUSValue(szRegPath, szValueName, REG_DWORD, &dwHide, sizeof(dwHide), SHREGSET_FORCE_HKCU); hr = HRESULT_FROM_WIN32(lRet); } } return hr; }