2018 lines
76 KiB
C++
2018 lines
76 KiB
C++
#include "priv.h"
|
|
|
|
#include <mstask.h>
|
|
#include "favorite.h"
|
|
#include "iehelpid.h"
|
|
#include "webcheck.h"
|
|
#include "chanmgr.h"
|
|
#include "chanmgrp.h"
|
|
#include "resource.h"
|
|
#include <platform.h>
|
|
#include <mobsync.h>
|
|
#include <mobsyncp.h>
|
|
|
|
#include <mluisupp.h>
|
|
|
|
|
|
UINT IE_ErrorMsgBox(IShellBrowser* psb,
|
|
HWND hwndOwner, HRESULT hrError, LPCWSTR szError, LPCTSTR pszURLparam,
|
|
UINT idResource, UINT wFlags);
|
|
void ReplaceTransplacedControls (HWND hDlgMaster, HWND hDlgTemplate);
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
// helper function for DoOrganizeFavDlgEx
|
|
// the org favs dialog returns a list of null terminated strings containing
|
|
// all the urls to update.
|
|
void OrgFavSynchronize(HWND hwnd, VARIANT *pvarUrlsToSynch)
|
|
{
|
|
#ifndef DISABLE_SUBSCRIPTIONS
|
|
|
|
ASSERT(pvarUrlsToSynch);
|
|
|
|
//if there are no urls to update, it's an empty string so bail
|
|
if ( (pvarUrlsToSynch->vt == VT_BSTR) && (pvarUrlsToSynch->bstrVal) &&
|
|
*(pvarUrlsToSynch->bstrVal) )
|
|
{
|
|
PWSTR pwzUrls = pvarUrlsToSynch->bstrVal;
|
|
|
|
ISubscriptionMgr *psm;
|
|
|
|
if (SUCCEEDED(JITCoCreateInstance(CLSID_SubscriptionMgr, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr,
|
|
(void**)&psm, hwnd, FIEF_FLAG_FORCE_JITUI)))
|
|
{
|
|
//SysStringLen doesn't look at the string contents, just the cb of the alloc
|
|
while (pwzUrls < (pvarUrlsToSynch->bstrVal + SysStringLen(pvarUrlsToSynch->bstrVal)))
|
|
{
|
|
psm->UpdateSubscription(pwzUrls);
|
|
pwzUrls += lstrlenW(pwzUrls) + 1;
|
|
}
|
|
|
|
psm->Release();
|
|
}
|
|
}
|
|
#endif /* !DISABLE_SUBSCRIPTIONS */
|
|
}
|
|
|
|
|
|
/*
|
|
* DoOrganizeFavDlgEx
|
|
*
|
|
* HWND hwnd Owner window for the dialog.
|
|
* LPWSTR pszInitDir Dir to use as root. if null, the user's favorites dir is used.
|
|
*
|
|
* Returns:
|
|
* BOOL. TRUE if succeeds. FALSE otherwise.
|
|
*
|
|
*/
|
|
|
|
BOOL WINAPI DoOrganizeFavDlgEx(HWND hwnd, LPWSTR pszInitDir)
|
|
{
|
|
// The easy answer would be to add an about:OrganizeFavorites that
|
|
// gets registered in our selfreg.inx file. Unfortunately, multilanguage
|
|
// support requires us to generate the URL on the fly.
|
|
|
|
WCHAR wszUrl[6 + MAX_PATH + 11 + 1]; // "res://MAX_PATH/orgfav.dlg"
|
|
|
|
StringCchCopy(wszUrl, ARRAYSIZE(wszUrl), L"res://");
|
|
|
|
if(SUCCEEDED(GetModuleFileNameWrapW(MLGetHinst(), wszUrl + 6, MAX_PATH)))
|
|
{
|
|
if(SUCCEEDED(StringCchCat(wszUrl, ARRAYSIZE(wszUrl), L"/orgfav.dlg")))
|
|
{
|
|
IMoniker *pmk;
|
|
if (SUCCEEDED(CreateURLMoniker(NULL, wszUrl, &pmk)))
|
|
{
|
|
ASSERT(pmk);
|
|
VARIANT varUrlsToSynch, varInitialDir;
|
|
BSTR bstrInitDir;
|
|
|
|
VariantInit(&varUrlsToSynch);
|
|
VariantInit(&varInitialDir);
|
|
|
|
if (pszInitDir)
|
|
{
|
|
bstrInitDir = SysAllocString(pszInitDir);
|
|
if (bstrInitDir)
|
|
{
|
|
varInitialDir.vt = VT_BSTR;
|
|
varInitialDir.bstrVal = bstrInitDir;
|
|
}
|
|
}
|
|
|
|
ShowHTMLDialog(hwnd, pmk, &varInitialDir, L"Resizable=1", &varUrlsToSynch);
|
|
OrgFavSynchronize(hwnd, &varUrlsToSynch);
|
|
|
|
if (pszInitDir && bstrInitDir)
|
|
SysFreeString(bstrInitDir);
|
|
VariantClear(&varUrlsToSynch);
|
|
pmk->Release();
|
|
return TRUE;
|
|
}
|
|
else
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
* DoOrganizeFavDlg
|
|
*
|
|
* This API is exported so that it may be called by explorer and mshtml in
|
|
* addition to being called internally by shdocvw.
|
|
*
|
|
* HWND hwndOwner Owner window for the dialog.
|
|
* LPWSTR pszInitDir Dir to use as root. if null, the user's favorites dir is used.
|
|
*
|
|
* Returns:
|
|
* BOOL. TRUE if succeeds. FALSE otherwise.
|
|
*
|
|
*/
|
|
|
|
BOOL WINAPI DoOrganizeFavDlg(HWND hwnd, LPSTR pszInitDir)
|
|
{
|
|
BOOL fRet;
|
|
WCHAR szInitDir[MAX_PATH];
|
|
|
|
if (pszInitDir)
|
|
{
|
|
SHAnsiToUnicode(pszInitDir, szInitDir, ARRAYSIZE(szInitDir));
|
|
fRet = DoOrganizeFavDlgEx(hwnd, szInitDir);
|
|
}
|
|
else
|
|
{
|
|
fRet = DoOrganizeFavDlgEx(hwnd, NULL);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL WINAPI DoOrganizeFavDlgW(HWND hwnd, LPWSTR pszInitDir)
|
|
{
|
|
return DoOrganizeFavDlgEx(hwnd, pszInitDir);
|
|
}
|
|
|
|
|
|
#define ADDTOFAVPROP TEXT("SHDOC_ATFPROP")
|
|
|
|
typedef enum { ATF_FAVORITE,
|
|
ATF_CHANNEL,
|
|
ATF_CHANNEL_MODIFY,
|
|
ATF_CHANNEL_SOFTDIST
|
|
} FAVDLGTYPE;
|
|
|
|
typedef struct _ADDTOFAV
|
|
{
|
|
PTSTR pszInitDir;
|
|
UINT cchInitDir;
|
|
PTSTR pszFile;
|
|
UINT cchFile;
|
|
LPITEMIDLIST pidl;
|
|
LPITEMIDLIST pidlSelected;
|
|
LPCITEMIDLIST pidlFavorite;
|
|
FAVDLGTYPE iDlgType;
|
|
SUBSCRIPTIONINFO siSubsInProg;
|
|
SUBSCRIPTIONTYPE subsType;
|
|
BOOL bIsSoftdist;
|
|
BOOL bStartSubscribed;
|
|
BOOL bSubscribed;
|
|
} ADDTOFAV;
|
|
|
|
BOOL IsSubscribed(ADDTOFAV *patf);
|
|
|
|
typedef struct _BFFFavSubStruct
|
|
{
|
|
WNDPROC lpfnOldWndProc;
|
|
HWND hwndNew;
|
|
HWND hwndTV;
|
|
HWND hwndSave;
|
|
HWND hTemplateWnd;
|
|
ADDTOFAV * patf;
|
|
RECT rcRestored;
|
|
} BFFFAVSUBSTRUCT;
|
|
|
|
BOOL_PTR CALLBACK NewFavDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
HWND hwnd;
|
|
ASSERT(lParam);
|
|
SetWindowLongPtr(hDlg, DWLP_USER, lParam);
|
|
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
|
|
// cross-lang platform support
|
|
SHSetDefaultDialogFont(hDlg, IDD_NAME);
|
|
hwnd = GetDlgItem(hDlg, IDD_NAME);
|
|
SendMessage(hwnd, EM_LIMITTEXT, MAX_PATH - 1, 0);
|
|
EnableOKButtonFromID(hDlg, IDD_NAME);
|
|
break;
|
|
}
|
|
case WM_DESTROY:
|
|
SHRemoveDefaultDialogFont(hDlg);
|
|
return FALSE;
|
|
|
|
case WM_COMMAND:
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDD_NAME:
|
|
{
|
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_UPDATE)
|
|
{
|
|
LPTSTR lpstrName = (LPTSTR) GetWindowLongPtr(hDlg, DWLP_USER);
|
|
EnableOKButtonFromID(hDlg, IDD_NAME);
|
|
GetDlgItemText(hDlg, IDD_NAME, lpstrName, MAX_PATH);
|
|
}
|
|
break;
|
|
}
|
|
|
|
case IDOK:
|
|
{
|
|
TCHAR szTmp[MAX_PATH];
|
|
HRESULT hr = StringCchCopy(szTmp, ARRAYSIZE(szTmp), (LPTSTR)GetWindowLongPtr(hDlg, DWLP_USER));
|
|
|
|
if(FAILED(hr) || PathCleanupSpec(NULL,szTmp))
|
|
{
|
|
HWND hwnd;
|
|
|
|
MLShellMessageBox(
|
|
hDlg,
|
|
MAKEINTRESOURCE(IDS_FAVS_INVALIDFN),
|
|
MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
|
|
MB_OK | MB_ICONHAND);
|
|
hwnd = GetDlgItem(hDlg, IDD_NAME);
|
|
SetWindowText(hwnd, TEXT('\0'));
|
|
EnableWindow(GetDlgItem(hDlg, IDOK), FALSE);
|
|
SetFocus(hwnd);
|
|
break;
|
|
}
|
|
}
|
|
// fall through
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, GET_WM_COMMAND_ID(wParam, lParam));
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
break;
|
|
|
|
default:
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
// BOGUS - these id's stolen from SHBrowseForFolder implementation
|
|
#define IDD_FOLDERLIST 0x3741
|
|
#define IDD_BROWSETITLE 0x3742
|
|
#define IDD_BROWSESTATUS 0x3743
|
|
|
|
const static DWORD aAddToFavHelpIDs[] = { // Context Help IDs
|
|
IDC_FAVORITE_DESC, NO_HELP,
|
|
IDD_BROWSETITLE, NO_HELP,
|
|
IDD_BROWSESTATUS, NO_HELP,
|
|
IDC_FAVORITE_ICON, NO_HELP,
|
|
IDC_NAMESTATIC, IDH_NAMEEDIT,
|
|
IDC_FOLDERLISTSTATIC, IDH_BROWSELIST,
|
|
IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER, IDH_BROWSELIST,
|
|
IDC_FAVORITE_NEWFOLDER, IDH_CREATEIN,
|
|
IDC_SUBSCRIBE_CUSTOMIZE, IDH_CHANNEL_SUBSCR_CUST_BUTTON,
|
|
IDC_FAVORITE_CREATEIN, IDH_NEWFOLDER,
|
|
IDC_FAVORITE_NAME, IDH_NAMEEDIT,
|
|
IDC_MAKE_OFFLINE, IDH_MAKE_AVAIL_OFFLINE,
|
|
0, 0
|
|
};
|
|
|
|
const static DWORD aAddToChanHelpIDs[] = { // Context Help IDs
|
|
IDC_FAVORITE_DESC, NO_HELP,
|
|
IDD_BROWSETITLE, NO_HELP,
|
|
IDD_BROWSESTATUS, NO_HELP,
|
|
IDC_FAVORITE_ICON, NO_HELP,
|
|
IDC_NAMESTATIC, IDH_NAMEEDIT,
|
|
IDC_FOLDERLISTSTATIC, IDH_BROWSELIST,
|
|
IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER, IDH_BROWSELIST,
|
|
IDC_FAVORITE_NEWFOLDER, IDH_CREATEIN,
|
|
IDC_SUBSCRIBE_CUSTOMIZE, IDH_CHANNEL_SUBSCR_CUST_BUTTON,
|
|
IDC_FAVORITE_CREATEIN, IDH_NEWFOLDER,
|
|
IDC_FAVORITE_NAME, IDH_NAMEEDIT,
|
|
IDC_MAKE_OFFLINE, IDH_MAKE_AVAIL_OFFLINE,
|
|
0, 0
|
|
};
|
|
|
|
/*
|
|
* Makes sure the item being added to favorites doesn't already exist. If it does,
|
|
* puts up a message box to have the user confirm whether they want to overwrite
|
|
* the old favorite or not.
|
|
*/
|
|
BOOL ConfirmAddToFavorites(HWND hwndOwner, ADDTOFAV * patf)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
BOOL fExists;
|
|
int iPromptString = 0;
|
|
|
|
if (patf->subsType == SUBSTYPE_CHANNEL)
|
|
{
|
|
//patf->pszInitDir now contains the path with a .url on the end; the channel
|
|
//will be stored in a directory of that name without .url. Strip it.
|
|
TCHAR szPath[MAX_PATH];
|
|
if(FAILED(StringCchCopy(szPath, ARRAYSIZE(szPath), patf->pszInitDir)))
|
|
{
|
|
MLShellMessageBox(
|
|
hwndOwner,
|
|
MAKEINTRESOURCE(IDS_FAVS_INVALIDFN),
|
|
MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
|
|
MB_OK | MB_ICONHAND);
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
PathRemoveExtension (szPath);
|
|
fExists = PathFileExists(szPath);
|
|
|
|
iPromptString = IDS_CHANNELS_FILEEXISTS;
|
|
|
|
}
|
|
else
|
|
{
|
|
fExists = PathFileExists(patf->pszInitDir);
|
|
iPromptString = IDS_FAVS_FILEEXISTS;
|
|
|
|
}
|
|
|
|
fRet = ! fExists ||
|
|
(MLShellMessageBox(
|
|
hwndOwner,
|
|
MAKEINTRESOURCE(iPromptString),
|
|
NULL, //use owner's title
|
|
MB_ICONQUESTION | MB_YESNO) == IDYES);
|
|
return fRet;
|
|
}
|
|
|
|
//
|
|
// Get the localized date and time
|
|
//
|
|
|
|
typedef HRESULT (*PFVARIANTTIMETOSYSTEMTIME)(DOUBLE, LPSYSTEMTIME);
|
|
|
|
|
|
//
|
|
// Subscribe to the current site.
|
|
//
|
|
|
|
HRESULT SubscribeToSite(HWND hwnd, LPCTSTR pszFile, LPCITEMIDLIST pidl, DWORD dwFlags,
|
|
SUBSCRIPTIONINFO* pSubs, SUBSCRIPTIONTYPE subsType)
|
|
{
|
|
#ifndef DISABLE_SUBSCRIPTIONS
|
|
|
|
TCHAR szURL[MAX_URL_STRING];
|
|
ISubscriptionMgr *pISubscriptionMgr;
|
|
|
|
//
|
|
// Get a displayable URL.
|
|
//
|
|
|
|
IEGetDisplayName(pidl, szURL, SHGDN_FORPARSING);
|
|
|
|
//
|
|
// Get a pointer to the subscription manager.
|
|
//
|
|
|
|
HRESULT hr = JITCoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISubscriptionMgr,
|
|
(void**)&pISubscriptionMgr, hwnd, FIEF_FLAG_FORCE_JITUI);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
//
|
|
// Create a default subscription.
|
|
//
|
|
BSTR bstrURL = SysAllocStringT(szURL);
|
|
if (bstrURL)
|
|
{
|
|
BSTR bstrName = SysAllocStringT(pszFile);
|
|
if (bstrName)
|
|
{
|
|
hr = pISubscriptionMgr->CreateSubscription(hwnd,
|
|
bstrURL, bstrName, dwFlags, subsType, pSubs);
|
|
SysFreeString(bstrName);
|
|
}
|
|
SysFreeString(bstrURL);
|
|
}
|
|
|
|
//
|
|
// Clean up.
|
|
//
|
|
|
|
pISubscriptionMgr->Release();
|
|
}
|
|
|
|
return hr;
|
|
#else /* !DISABLE_SUBSCRIPTIONS */
|
|
|
|
return E_FAIL;
|
|
|
|
#endif /* !DISABLE_SUBSCRIPTIONS */
|
|
}
|
|
|
|
|
|
//
|
|
// Create in-memory subscription, but only optionally save it to subscription manager
|
|
//
|
|
|
|
BOOL StartSiteSubscription (HWND hwnd, ADDTOFAV* patf, BOOL bFinalize)
|
|
{
|
|
#ifndef DISABLE_SUBCRIPTIONS
|
|
|
|
//update the changes-only flag (radio buttons here are, effectively, direct access to this flag)
|
|
if (patf->subsType == SUBSTYPE_CHANNEL || patf->subsType == SUBSTYPE_DESKTOPCHANNEL)
|
|
{
|
|
//if set, leave alone; otherwise, put to full download
|
|
if (!(patf->siSubsInProg.fChannelFlags & CHANNEL_AGENT_PRECACHE_SOME))
|
|
patf->siSubsInProg.fChannelFlags |= CHANNEL_AGENT_PRECACHE_ALL;
|
|
|
|
patf->siSubsInProg.fUpdateFlags |= SUBSINFO_CHANNELFLAGS | SUBSINFO_SCHEDULE;
|
|
}
|
|
|
|
if (S_OK != SubscribeToSite(hwnd, patf->pszFile, patf->pidlFavorite,
|
|
bFinalize ? CREATESUBS_NOUI | CREATESUBS_FROMFAVORITES : CREATESUBS_NOSAVE,
|
|
&patf->siSubsInProg, patf->subsType))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
#else /* !DISABLE_SUBSCRIPTIONS */
|
|
|
|
return FALSE;
|
|
|
|
#endif /* !DISABLE_SUBSCRIPTIONS */
|
|
}
|
|
|
|
/*
|
|
Combines the path and the filename of the favorite
|
|
and puts it into patf->pszInitDir, so that it has the fully qualified pathname.
|
|
*/
|
|
#define SZ_URLEXT TEXT(".url")
|
|
#define CCH_URLEXT SIZECHARS(SZ_URLEXT)
|
|
|
|
BOOL QualifyFileName(ADDTOFAV *patf)
|
|
{
|
|
TCHAR szTemp[MAX_PATH];
|
|
BOOL fRet = FALSE;
|
|
LPTSTR pstr;
|
|
|
|
// Can we safely add the extension to this?
|
|
if (lstrlen(patf->pszFile) < (int)(patf->cchFile - CCH_URLEXT))
|
|
{
|
|
//Add extension .url if its not already there
|
|
//This is to prevent strings like "com" in "www.microsoft.com" from being interpreted as extensions
|
|
|
|
pstr = PathFindExtension(patf->pszFile);
|
|
if (!pstr || (pstr && StrCmpI(pstr, SZ_URLEXT)))// && StrCmpI(pstr, SZ_CDFEXT)))
|
|
{
|
|
if(FAILED(StringCchCat(patf->pszFile, patf->cchFile, SZ_URLEXT)))
|
|
return FALSE;
|
|
}
|
|
|
|
// Is there a folder associated with the filename?
|
|
if (patf->pidlSelected && SHGetPathFromIDList(patf->pidlSelected, szTemp))
|
|
{
|
|
// Yes
|
|
if (PathCombine(szTemp, szTemp, patf->pszFile))
|
|
{
|
|
if ((UINT)lstrlen(szTemp) < patf->cchInitDir)
|
|
{
|
|
if(SUCCEEDED(StringCchCopy(patf->pszInitDir, patf->cchInitDir, szTemp)))
|
|
fRet = TRUE;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
BOOL SubscriptionFailsChannelAuthentication (HWND hDlg, SUBSCRIPTIONINFO* psi)
|
|
{
|
|
#ifndef DISABLE_SUBSCRIPTIONS
|
|
|
|
if (psi->bNeedPassword && !(psi->bstrPassword && psi->bstrPassword[0]
|
|
&& psi->bstrUserName && psi->bstrUserName[0]))
|
|
{ //password would be required
|
|
if (IsDlgButtonChecked (hDlg, IDC_MAKE_OFFLINE))
|
|
{ //they're trying to subscribe... WRONG!
|
|
MLShellMessageBox(
|
|
hDlg,
|
|
MAKEINTRESOURCE(IDS_NEED_CHANNEL_PASSWORD),
|
|
NULL,
|
|
MB_ICONINFORMATION | MB_OK);
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
|
|
#else /* !DISABLE_SUBSCRIPTIONS */
|
|
|
|
return FALSE;
|
|
|
|
#endif /* !DISABLE_SUBSCRIPTIONS */
|
|
}
|
|
|
|
|
|
LRESULT CALLBACK BFFFavSubclass(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
BFFFAVSUBSTRUCT * pbffFS = (BFFFAVSUBSTRUCT *)GetProp(hwnd, ADDTOFAVPROP);
|
|
WNDPROC lpfnOldWndProc = pbffFS->lpfnOldWndProc;
|
|
RECT rc;
|
|
|
|
switch (uMsg) {
|
|
case WM_COMMAND:
|
|
// Intercept the command for the New Folder button we hacked into
|
|
// the SHBrowseForFolder dialog.
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam)) {
|
|
case IDC_FAVORITE_NAME:
|
|
{
|
|
HWND hwndedit;
|
|
if (GET_WM_COMMAND_CMD(wParam, lParam) == EN_CHANGE)
|
|
EnableOKButtonFromID(hwnd, IDC_FAVORITE_NAME);
|
|
hwndedit = GetDlgItem(hwnd, IDC_FAVORITE_NAME);
|
|
SendMessage(hwndedit, EM_LIMITTEXT, MAX_PATH - 1, 0);
|
|
break;
|
|
}
|
|
|
|
case IDC_MAKE_OFFLINE:
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SUBSCRIBE_CUSTOMIZE),
|
|
IsDlgButtonChecked(hwnd, IDC_MAKE_OFFLINE));
|
|
break;
|
|
|
|
case IDC_SUBSCRIBE_CUSTOMIZE:
|
|
//need to create -- but not store -- subscription
|
|
if (StartSiteSubscription (hwnd, pbffFS->patf, FALSE))
|
|
SendMessage (hwnd, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hwnd, IDOK), TRUE);
|
|
break;
|
|
|
|
case IDC_FAVORITE_NEWFOLDER:
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR szName[MAX_PATH];
|
|
HWND hwndTV;
|
|
TV_ITEM tv_item;
|
|
|
|
// Bring up the Create New Folder dialog
|
|
if ((DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(DLG_NEWFOLDER), hwnd,
|
|
NewFavDlgProc, (LPARAM)szName) == IDOK) &&
|
|
(SHGetPathFromIDList(pbffFS->patf->pidlSelected, szPath)) &&
|
|
((lstrlen(szPath) + lstrlen(szName) + 1) < MAX_PATH))
|
|
{
|
|
PathCombine(szPath, szPath, szName);
|
|
|
|
BOOL bSuccess = FALSE;
|
|
|
|
#ifdef CREATEFOLDERSINCHANNELSDIR
|
|
if (pbffFS->patf->subsType == SUBSTYPE_CHANNEL)
|
|
{
|
|
ASSERT(0); //should not be possible in this release
|
|
//(I removed this button in the .rc dialogs for channels)
|
|
|
|
//Note: to make this work in a future release, reenable this code -- it's
|
|
//functional. But the folders created here show up ugly in the channel bar
|
|
//(just a default folder icon) and if you click on them, you get a shell
|
|
//Explorer window instead of a theater-mode browser window. The reason
|
|
//for this second happening is that the desktop.ini file created in the new
|
|
//folder has no URL=. To remedy this: AddCategory() has to be fixed so it
|
|
//doesn't interpret the pszURL argument as a UNC name (I was using a resouce moniker
|
|
//pointing into cdfview.dll for the html target), and the OC hosted by the default
|
|
//html pages has to learn how to be hosted from a html page without a path -- or we
|
|
//actually have to create an html page in the new directory, which is messy.
|
|
IChannelMgr* pChanMgr;
|
|
HRESULT hr;
|
|
|
|
hr = JITCoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IChannelMgr, (void**)&pChanMgr,
|
|
hwnd, FIEF_FLAG_FORCE_JITUI);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
IChannelMgrPriv* pChanMgrPriv;
|
|
hr = pChanMgr->QueryInterface (IID_IChannelMgrPriv, (void**)&pChanMgrPriv);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
char szCFPath[MAX_PATH];
|
|
WCHAR wszFolder[MAX_PATH];
|
|
IChannelMgrPriv::CHANNELFOLDERLOCATION cflLocation =
|
|
(pbffFS->patf->iDlgType == ATF_CHANNEL_SOFTDIST ?
|
|
IChannelMgrPriv::CF_SOFTWAREUPDATE :
|
|
IChannelMgrPriv::CF_CHANNEL);
|
|
hr = pChanMgrPriv->GetChannelFolderPath (szCFPath, ARRAYSIZE(szCFPath), cflLocation);
|
|
|
|
int cchCommon = PathCommonPrefix (szPath, szCFPath, NULL);
|
|
AnsiToUnicode (szPath + cchCommon, wszFolder, ARRAYSIZE(wszFolder));
|
|
|
|
CHANNELCATEGORYINFO info = {0};
|
|
info.cbSize = sizeof(info);
|
|
info.pszTitle = wszFolder;
|
|
bSuccess = SUCCEEDED (pChanMgr->AddCategory (&info));
|
|
|
|
pChanMgrPriv->Release();
|
|
}
|
|
|
|
pChanMgr->Release();
|
|
}
|
|
}
|
|
else
|
|
#endif
|
|
{
|
|
bSuccess = CreateDirectory(szPath, NULL);
|
|
}
|
|
|
|
if (bSuccess)
|
|
{
|
|
// This code assumes the layout of SHBrowseForFolder!
|
|
|
|
// directory successfully created, must notify registered shell components.
|
|
SHChangeNotify(SHCNE_MKDIR, SHCNF_PATH, szPath, NULL);
|
|
// Get the TreeView control
|
|
hwndTV = GetDlgItem(hwnd, IDD_FOLDERLIST);
|
|
if (hwndTV) {
|
|
HTREEITEM hti = TreeView_GetSelection(hwndTV);
|
|
// Take the selected item and reset it, then reexpand it so
|
|
// that it shows the new directory we just created.
|
|
tv_item.mask = TVIF_CHILDREN;
|
|
tv_item.hItem = hti;
|
|
tv_item.cChildren = -1;
|
|
TreeView_SetItem(hwndTV, &tv_item);
|
|
TreeView_Expand(hwndTV, hti, TVE_COLLAPSE | TVE_COLLAPSERESET);
|
|
TreeView_Expand(hwndTV, hti, TVE_EXPAND);
|
|
|
|
// Find the new directory we just created and select it by
|
|
// walking the tree from the selected item down.
|
|
if (hti = TreeView_GetChild(hwndTV, hti)) {
|
|
tv_item.mask = TVIF_TEXT;
|
|
tv_item.pszText = szPath;
|
|
tv_item.cchTextMax = MAX_PATH;
|
|
do {
|
|
tv_item.hItem = hti;
|
|
TreeView_GetItem(hwndTV, &tv_item);
|
|
if (StrCmp(szName, szPath) == 0) {
|
|
TreeView_Select(hwndTV, hti, TVGN_CARET);
|
|
break;
|
|
}
|
|
} while (hti = TreeView_GetNextSibling(hwndTV, hti));
|
|
}
|
|
SetFocus(hwndTV);
|
|
}
|
|
} else {
|
|
|
|
LPVOID lpMsgBuf;
|
|
|
|
if(FormatMessage(
|
|
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
|
|
NULL,
|
|
GetLastError(),
|
|
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
|
|
(LPTSTR) &lpMsgBuf,
|
|
0,
|
|
NULL
|
|
))
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
(LPCTSTR)lpMsgBuf,
|
|
MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
|
|
MB_ICONINFORMATION | MB_OK);
|
|
|
|
// Free the buffer.
|
|
LocalFree( lpMsgBuf );
|
|
}
|
|
lpMsgBuf = NULL;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDOK:
|
|
// first, make sure they're not trying to subscribe to an authenticated
|
|
// channel without entering a password.
|
|
if (SubscriptionFailsChannelAuthentication (hwnd, &pbffFS->patf->siSubsInProg))
|
|
return FALSE;
|
|
|
|
// Retrieve the text from the Name edit control.
|
|
GetDlgItemText(hwnd, IDC_FAVORITE_NAME, pbffFS->patf->pszFile, pbffFS->patf->cchFile);
|
|
{ // Just a block to declare variables
|
|
BOOL fTooBig = TRUE; // assume failure
|
|
TCHAR szTmp[MAX_PATH];
|
|
|
|
if (lstrlen(pbffFS->patf->pszFile) < MAX_PATH)
|
|
{
|
|
if(FAILED((StringCchCopy(szTmp, ARRAYSIZE(szTmp), pbffFS->patf->pszFile))))
|
|
return FALSE;
|
|
|
|
// PathCleanupSpec deals with MAX_PATH buffers, so we should be fine
|
|
if (PathCleanupSpec(NULL, szTmp))
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_FAVS_INVALIDFN),
|
|
MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
|
|
MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
|
|
// Make sure the name is unique and if not, that the user has
|
|
// specified that it is OK to override.
|
|
if (QualifyFileName(pbffFS->patf))
|
|
{
|
|
if (!ConfirmAddToFavorites(hwnd, pbffFS->patf))
|
|
return FALSE;
|
|
|
|
// Bogus hack since the ATF stuff is only half done
|
|
// Depending on which dlg is shown, look for the appropriate
|
|
// check.
|
|
if (IsDlgButtonChecked (hwnd, IDC_MAKE_OFFLINE))
|
|
{
|
|
//they want to subscribe! save subscription we already have in memory
|
|
//trouble is, pbffFS->patf->pszFile ends in a bogus .url
|
|
TCHAR* pszTemp = pbffFS->patf->pszFile;
|
|
TCHAR szNoExt[MAX_PATH];
|
|
if(FAILED((StringCchCopy(szNoExt, ARRAYSIZE(szNoExt), pbffFS->patf->pszFile))))
|
|
return FALSE;
|
|
|
|
pbffFS->patf->pszFile = szNoExt;
|
|
PathRemoveExtension (szNoExt);
|
|
pbffFS->patf->bSubscribed =
|
|
StartSiteSubscription (hwnd, pbffFS->patf, TRUE);
|
|
pbffFS->patf->pszFile = pszTemp;
|
|
}
|
|
else if (pbffFS->patf->bStartSubscribed)
|
|
{
|
|
// If we started subscribed and they unchecked make available
|
|
// offline, then delete the subscription.
|
|
|
|
ISubscriptionMgr* pSubsMgr;
|
|
if (SUCCEEDED (CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISubscriptionMgr, (void**)&pSubsMgr)))
|
|
{
|
|
//url is in patf->pidlFavorite
|
|
WCHAR wszURL[MAX_URL_STRING];
|
|
IEGetDisplayName(pbffFS->patf->pidlFavorite, wszURL, SHGDN_FORPARSING);
|
|
|
|
pSubsMgr->DeleteSubscription(wszURL, NULL);
|
|
pSubsMgr->Release();
|
|
}
|
|
}
|
|
|
|
// Enable and set focus to the tree view so that it is sure to
|
|
// be selected so that SHBrowseForFolder will return a pidl.
|
|
EnableWindow(pbffFS->hwndTV, TRUE);
|
|
SetFocus(pbffFS->hwndTV);
|
|
fTooBig = FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
if (fTooBig)
|
|
{
|
|
MLShellMessageBox(
|
|
hwnd,
|
|
MAKEINTRESOURCE(IDS_FAVS_FNTOOLONG),
|
|
MAKEINTRESOURCE(IDS_FAVS_ADDTOFAVORITES),
|
|
MB_OK | MB_ICONHAND);
|
|
return FALSE;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case IDC_FAVORITE_CREATEIN:
|
|
// The advanced button has been clicked. Enable/disable the tree view
|
|
// and New button, set focus to the tree view or ok button, disable the advanced
|
|
// button and then resize the dialog.
|
|
{
|
|
BOOL fExpanding = !IsWindowEnabled(GetDlgItem(hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER)); //random control that gets enabled when dialog expanded
|
|
TCHAR szBuffer[100];
|
|
|
|
EnableWindow(pbffFS->hwndTV, fExpanding);
|
|
//don't show New Folder button for channels in the channels folder,
|
|
// see code for case IDC_FAVORITE_NEWFOLDER for why
|
|
if (fExpanding && pbffFS->patf->subsType == SUBSTYPE_CHANNEL)
|
|
{
|
|
LPITEMIDLIST pidlFavs = NULL;
|
|
TCHAR tzFavsPath[MAX_PATH];
|
|
|
|
if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_FAVORITES, &pidlFavs))
|
|
&& SUCCEEDED(SHGetNameAndFlags(pidlFavs, SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, tzFavsPath, SIZECHARS(tzFavsPath), NULL))
|
|
&& StrCmpNI(tzFavsPath, pbffFS->patf->pszInitDir, ARRAYSIZE(tzFavsPath))==0)
|
|
{
|
|
EnableWindow(pbffFS->hwndNew, TRUE);
|
|
}
|
|
if(pidlFavs)
|
|
ILFree(pidlFavs);
|
|
}
|
|
else
|
|
EnableWindow(pbffFS->hwndNew, fExpanding);
|
|
|
|
GetWindowRect(hwnd, &rc);
|
|
if (fExpanding)
|
|
{
|
|
int lRet = MLLoadString(IDS_FAVS_ADVANCED_COLLAPSE, szBuffer, ARRAYSIZE(szBuffer));
|
|
ASSERT(lRet);
|
|
|
|
SetFocus(pbffFS->hwndTV);
|
|
|
|
MoveWindow(hwnd, rc.left, rc.top,
|
|
pbffFS->rcRestored.right - pbffFS->rcRestored.left,
|
|
pbffFS->rcRestored.bottom - pbffFS->rcRestored.top, TRUE);
|
|
}
|
|
else
|
|
{
|
|
int lRet = MLLoadString(IDS_FAVS_ADVANCED_EXPAND, szBuffer, ARRAYSIZE(szBuffer));
|
|
ASSERT(lRet);
|
|
|
|
SetFocus(GetDlgItem(hwnd, IDC_FAVORITE_NAME));
|
|
|
|
MoveWindow(hwnd, rc.left, rc.top,
|
|
pbffFS->rcRestored.right - pbffFS->rcRestored.left,
|
|
pbffFS->rcRestored.bottom - pbffFS->rcRestored.top, TRUE);
|
|
|
|
// hide the bottom part of the dialog
|
|
int cx, cy;
|
|
RECT rc;
|
|
GetWindowRect (GetDlgItem (hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER), &rc);
|
|
cy = rc.top;
|
|
GetWindowRect (hwnd, &rc);
|
|
cx = rc.right - rc.left;
|
|
cy = cy /*top of ctrl*/ - rc.top; /*top of window*/
|
|
SetWindowPos (hwnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);
|
|
}
|
|
SetWindowText(GetDlgItem(hwnd, IDC_FAVORITE_CREATEIN), szBuffer);
|
|
|
|
break;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
{
|
|
DWORD dwValue = IsWindowEnabled(GetDlgItem(hwnd, IDC_FAVORITE_NEWFOLDER)); //random control that gets enabled when dialog expanded
|
|
|
|
SHRegSetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"), TEXT("AddToFavoritesExpanded"),
|
|
REG_DWORD, &dwValue, 4, SHREGSET_HKCU | SHREGSET_FORCE_HKCU);
|
|
ReplaceTransplacedControls (hwnd, pbffFS->hTemplateWnd);
|
|
DestroyWindow (pbffFS->hTemplateWnd);
|
|
SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR) lpfnOldWndProc);
|
|
RemoveProp(hwnd, ADDTOFAVPROP);
|
|
SHRemoveDefaultDialogFont(hwnd);
|
|
ILFree(pbffFS->patf->pidlSelected);
|
|
LocalFree((HLOCAL)pbffFS);
|
|
pbffFS = NULL;
|
|
break;
|
|
}
|
|
case WM_HELP:
|
|
SHWinHelpOnDemandWrap((HWND)((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
|
|
HELP_WM_HELP, (DWORD_PTR)(LPTSTR) (pbffFS->patf->iDlgType == ATF_FAVORITE
|
|
? aAddToFavHelpIDs : aAddToChanHelpIDs));
|
|
return TRUE;
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile, HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPVOID) (pbffFS->patf->iDlgType == ATF_FAVORITE
|
|
? aAddToFavHelpIDs : aAddToChanHelpIDs));
|
|
return TRUE;
|
|
break;
|
|
|
|
}
|
|
|
|
return CallWindowProc(lpfnOldWndProc, hwnd, uMsg, wParam, lParam);
|
|
}
|
|
|
|
|
|
static const TCHAR szTransplacedProp[] = TEXT("tp");
|
|
void ReplaceTransplacedControls (HWND hDlgMaster, HWND hDlgTemplate)
|
|
{
|
|
/*
|
|
* This function moves the controls that we moved from our temporary
|
|
* dialog over to SHBrowseForFolder's dialog, back to their original
|
|
* home, before they get destroyed. This is because otherwise we have
|
|
* problems when destroying the template dialog -- specifically, we get
|
|
* a GP fault in user.exe when destroying the edit control, because it
|
|
* looks to its parent window to figure out where its data segment is.
|
|
*
|
|
* Solution: (for safety) -- put everything back where it came from.
|
|
* Other possibilities: just move the edit control (by ID) back, or
|
|
* move all edit controls back, or use DS_LOCALEDIT for edit controls
|
|
* (but this is documented only for use with multiline edits.)
|
|
* Or modify SHBrowseForFolder to allow other dialog templates...
|
|
* but that's over in shell32.
|
|
*/
|
|
HWND hCtrl = GetWindow (hDlgMaster, GW_CHILD);
|
|
while (hCtrl)
|
|
{
|
|
HWND hNext = GetWindow (hCtrl, GW_HWNDNEXT);
|
|
|
|
if (GetProp (hCtrl, szTransplacedProp) != NULL)
|
|
{
|
|
RemoveProp (hCtrl, szTransplacedProp);
|
|
SetParent (hCtrl, hDlgTemplate);
|
|
}
|
|
|
|
hCtrl = hNext;
|
|
}
|
|
}
|
|
|
|
#define szOriginalWND TEXT("WorkaroundOrigWndProc")
|
|
INT_PTR CALLBACK MergeFavoritesDialogControls(HWND hDlgTemplate, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
HWND hDlgMaster = (HWND)lParam;
|
|
ASSERT (IsWindow (hDlgMaster));
|
|
|
|
TCHAR szT[200];
|
|
RECT rc;
|
|
|
|
//resize master like us
|
|
GetWindowText (hDlgTemplate, szT, ARRAYSIZE(szT));
|
|
SetWindowText (hDlgMaster, szT);
|
|
GetClientRect (hDlgTemplate, &rc);
|
|
AdjustWindowRect (&rc, GetWindowLong (hDlgMaster, GWL_STYLE), FALSE);
|
|
SetWindowPos (hDlgMaster, NULL, 0, 0, rc.right - rc.left, rc.bottom - rc.top,
|
|
SWP_NOMOVE | SWP_NOZORDER);
|
|
// a-msadek; If the owned window is mirrored, a dialog with specifed
|
|
// coordinates, the dialog get moved to the worng direction
|
|
HWND hWndOwner = GetWindow(hDlgMaster, GW_OWNER);
|
|
|
|
if(IS_WINDOW_RTL_MIRRORED(hWndOwner))
|
|
{
|
|
RECT rcOwner, rcDlg;
|
|
GetWindowRect(hWndOwner, &rcOwner);
|
|
GetWindowRect(hDlgMaster, &rcDlg);
|
|
SetWindowPos(hDlgMaster, NULL, rcDlg.left - (rcDlg.right - rcOwner.right), rcDlg.top, 0 ,0,
|
|
SWP_NOSIZE | SWP_NOZORDER);
|
|
}
|
|
|
|
|
|
#if 0 //now we do this as part of the "move controls from template to master" process,
|
|
//if we notice that a ctrl with that id already exists. This way we pick up the
|
|
//tab order too. If someone decides my hack (SetParent) to change tab order is
|
|
//broken, then that code can be nuked and this reenabled.
|
|
|
|
//position already-existing controls in master like us
|
|
int ID_PREEXIST_CTRLS[] = { IDOK_PLACEHOLDER, IDCANCEL_PLACEHOLDER,
|
|
IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER };
|
|
|
|
for (int iCtrl = 0; iCtrl < ARRAYSIZE(ID_PREEXIST_CTRLS); iCtrl++)
|
|
{
|
|
GetWindowRect (GetDlgItem (hDlgTemplate, ID_PREEXIST_CTRLS[iCtrl]), &rc);
|
|
MapWindowPoints (NULL, hDlgTemplate, (LPPOINT)&rc, 2);
|
|
MoveWindow (GetDlgItem (hDlgMaster, ID_PREEXIST_CTRLS[iCtrl]),
|
|
rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
|
|
|
|
DestroyWindow (GetDlgItem (hDlgTemplate, ID_PREEXIST_CTRLS[iCtrl]));
|
|
}
|
|
#endif
|
|
|
|
//copy other controls from us to master
|
|
//find last child
|
|
HWND hCtrlTemplate = NULL;
|
|
HWND hNextCtrl = GetWindow (hDlgTemplate, GW_CHILD);
|
|
if (hNextCtrl) //can't see how this would fail, but...
|
|
hCtrlTemplate = GetWindow (hNextCtrl, GW_HWNDLAST);
|
|
|
|
//have last window in hCtrlTemplate
|
|
//now move controls over in reverse order -- they'll end up stacking up in original order from template
|
|
while (hCtrlTemplate)
|
|
{
|
|
hNextCtrl = GetWindow (hCtrlTemplate, GW_HWNDPREV);
|
|
DWORD id = GetWindowLong (hCtrlTemplate, GWL_ID);
|
|
HWND hCtrlExisting;
|
|
if (id != (USHORT)IDC_STATIC && NULL != (hCtrlExisting = GetDlgItem (hDlgMaster, id)))
|
|
//it's one of the controls pre-created by SHBrowseForFolder
|
|
{ //so don't move this one over -- adjust existing control for size, position, tab order
|
|
RECT rc;
|
|
GetWindowRect (hCtrlTemplate, &rc);
|
|
MapWindowPoints (NULL, hDlgTemplate, (LPPOINT)&rc, 2);
|
|
SetWindowPos (hCtrlExisting, NULL, rc.left, rc.top,
|
|
rc.right - rc.left, rc.bottom - rc.top, SWP_NOACTIVATE | SWP_NOZORDER);
|
|
DestroyWindow (hCtrlTemplate);
|
|
//REVIEW
|
|
//hack -- send control to end of tab order
|
|
SetParent (hCtrlExisting, hDlgTemplate);
|
|
SetParent (hCtrlExisting, hDlgMaster);
|
|
}
|
|
else //we should move this control from template to master
|
|
{
|
|
SetProp (hCtrlTemplate, szTransplacedProp, (HANDLE)TRUE); //anything -- it's the existence of the prop that we check for
|
|
SetParent (hCtrlTemplate, hDlgMaster); //to know to move this control back later
|
|
}
|
|
hCtrlTemplate = hNextCtrl;
|
|
}
|
|
// Let Template know about the child so that it can forward WM_COMMAND notifications to it
|
|
// to work around the fact that edit controls cache their parent pointers and ignore SetParents
|
|
// when it comes to sending parent notifications
|
|
SetProp(hDlgTemplate, szOriginalWND, hDlgMaster);
|
|
}
|
|
|
|
break;
|
|
case WM_COMMAND:
|
|
// Workaround for above bug
|
|
SendMessage((HWND)GetProp(hDlgTemplate, szOriginalWND), uMsg, wParam, lParam);
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
int CALLBACK BFFFavCallback(HWND hwnd, UINT uMsg, LPARAM lParam, LPARAM lpData)
|
|
{
|
|
switch (uMsg)
|
|
{
|
|
case BFFM_INITIALIZED:
|
|
{
|
|
ADDTOFAV* patf = (ADDTOFAV*)lpData;
|
|
ASSERT (patf);
|
|
|
|
HWND hDlgTemp = CreateDialogParam(MLGetHinst(),
|
|
MAKEINTRESOURCE(IDD_ADDTOFAVORITES_TEMPLATE),
|
|
NULL, MergeFavoritesDialogControls, (LPARAM)hwnd);
|
|
//this results in all the controls being copied over
|
|
|
|
//if successful, make our other modifications
|
|
BFFFAVSUBSTRUCT * pbffFavSubStruct;
|
|
if ((IsWindow(GetDlgItem(hwnd, IDC_SUBSCRIBE_CUSTOMIZE))) //verify existence of randomly-selected control
|
|
&& (pbffFavSubStruct = (BFFFAVSUBSTRUCT *) LocalAlloc(LPTR, sizeof(BFFFAVSUBSTRUCT))))
|
|
{
|
|
//done with template, but don't destroy it:
|
|
//see MSKB Q84190, owner/owned vs parent/child -- the children
|
|
// of template are now children of master, but still OWNED
|
|
// by template, and are destroyed when template is destroyed...
|
|
// but we'll just keep template around
|
|
// invisibly.
|
|
//we'll take care of it when we go away
|
|
|
|
//Do we need to do SetDefaultDialogFont stuff for localization still, since it all comes from the .rc?
|
|
|
|
//set up window stuff for subclass:
|
|
// Get the TreeView control so we can muck with the style bits and move it down
|
|
HWND hwndT;
|
|
if (hwndT = GetDlgItem(hwnd, IDD_FOLDERLIST))
|
|
{
|
|
DWORD dwStyle = GetWindowLong(hwndT, GWL_STYLE);
|
|
dwStyle |= TVS_SHOWSELALWAYS;
|
|
dwStyle &= ~TVS_LINESATROOT;
|
|
SetWindowLong(hwndT, GWL_STYLE, dwStyle);
|
|
}
|
|
|
|
// don't allow subscriptions if the URL is not "http:" protocol, or if already subscribed
|
|
TCHAR szURL[MAX_URL_STRING];
|
|
|
|
if (!patf->pidlFavorite ||
|
|
FAILED(IEGetDisplayName(patf->pidlFavorite, szURL, SHGDN_FORPARSING)) ||
|
|
SHRestricted2(REST_NoAddingSubscriptions, szURL, 0) ||
|
|
!IsSubscribable(szURL) ||
|
|
!IsFeaturePotentiallyAvailable(CLSID_SubscriptionMgr) ||
|
|
!IsBrowserFrameOptionsPidlSet(patf->pidlFavorite, BFO_USE_IE_OFFLINE_SUPPORT))
|
|
{
|
|
CheckDlgButton(hwnd, IDC_MAKE_OFFLINE, 0);
|
|
EnableWindow(GetDlgItem (hwnd, IDC_MAKE_OFFLINE), FALSE);
|
|
EnableWindow(GetDlgItem (hwnd, IDC_SUBSCRIBE_CUSTOMIZE), FALSE);
|
|
}
|
|
else if (IsSubscribed(patf))
|
|
{
|
|
patf->bStartSubscribed = TRUE;
|
|
CheckDlgButton(hwnd, IDC_MAKE_OFFLINE, 1);
|
|
}
|
|
else if (patf->bIsSoftdist)
|
|
{
|
|
CheckDlgButton(hwnd, IDC_MAKE_OFFLINE, 1);
|
|
}
|
|
EnableWindow(GetDlgItem(hwnd, IDC_SUBSCRIBE_CUSTOMIZE),
|
|
IsDlgButtonChecked(hwnd, IDC_MAKE_OFFLINE));
|
|
|
|
//set the name
|
|
Edit_LimitText(GetDlgItem(hwnd, IDC_FAVORITE_NAME), MAX_PATH - 1);
|
|
|
|
// Use URL if title string is not displayable
|
|
if (SHIsDisplayable(patf->pszFile, g_fRunOnFE, g_bRunOnNT5))
|
|
{
|
|
SetDlgItemText(hwnd, IDC_FAVORITE_NAME, patf->pszFile);
|
|
}
|
|
else
|
|
{
|
|
TCHAR szUrlTemp[MAX_URL_STRING];
|
|
IEGetDisplayName(patf->pidlFavorite, szUrlTemp, SHGDN_FORPARSING);
|
|
SetDlgItemText(hwnd, IDC_FAVORITE_NAME, szUrlTemp);
|
|
}
|
|
|
|
EnableOKButtonFromID(hwnd, IDC_FAVORITE_NAME);
|
|
|
|
|
|
// hide the (empty) SHBrowseForFolder prompt control
|
|
ShowWindow(GetDlgItem (hwnd, IDD_BROWSETITLE), SW_HIDE);
|
|
|
|
// Fill out the structure and set it as a property so that our subclass
|
|
// proc can get to this data.
|
|
pbffFavSubStruct->lpfnOldWndProc = (WNDPROC) SetWindowLongPtr(hwnd, GWLP_WNDPROC, (LONG_PTR)BFFFavSubclass);
|
|
pbffFavSubStruct->hwndNew = GetDlgItem(hwnd, IDC_FAVORITE_NEWFOLDER);
|
|
pbffFavSubStruct->patf = patf;
|
|
pbffFavSubStruct->hwndTV = GetDlgItem(hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER);
|
|
pbffFavSubStruct->hwndSave = GetDlgItem(hwnd, IDC_FAVORITE_CREATEIN);
|
|
pbffFavSubStruct->hTemplateWnd = hDlgTemp; //save for explicit destruction later
|
|
GetWindowRect(hwnd, &(pbffFavSubStruct->rcRestored));
|
|
|
|
SetProp(hwnd, ADDTOFAVPROP, (HANDLE)pbffFavSubStruct);
|
|
|
|
patf->pidlSelected = ILClone(patf->pidl);
|
|
|
|
DWORD dwType, dwValue = 0, dwcData = sizeof(dwValue);
|
|
TCHAR szBuffer[100];
|
|
|
|
SHRegGetUSValue(TEXT("Software\\Microsoft\\Internet Explorer\\Main"), TEXT("AddToFavoritesExpanded"),
|
|
&dwType, &dwValue, &dwcData, 0, NULL, sizeof(dwValue));
|
|
|
|
if (dwValue == 0)
|
|
{
|
|
int lRet = MLLoadString(IDS_FAVS_ADVANCED_EXPAND, szBuffer, ARRAYSIZE(szBuffer));
|
|
ASSERT(lRet);
|
|
|
|
// Disable the tree view and new button so that we can't tab to them.
|
|
EnableWindow(GetDlgItem (hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER), FALSE);
|
|
EnableWindow(GetDlgItem (hwnd, IDC_FAVORITE_NEWFOLDER), FALSE);
|
|
|
|
// hide the bottom part of the dialog
|
|
int cx, cy;
|
|
RECT rc;
|
|
GetWindowRect (GetDlgItem (hwnd, IDC_SUBSCRIBE_FOLDERLIST_PLACEHOLDER), &rc);
|
|
cy = rc.top;
|
|
GetWindowRect (hwnd, &rc);
|
|
cx = rc.right - rc.left;
|
|
cy = cy /*top of ctrl*/ - rc.top; /*top of window*/
|
|
SetWindowPos (hwnd, NULL, 0, 0, cx, cy, SWP_NOMOVE | SWP_NOZORDER);
|
|
}
|
|
else
|
|
{
|
|
//don't show New Folder button for channels in the channels folder,
|
|
// see code for case IDC_FAVORITE_NEWFOLDER for why
|
|
if (patf->subsType == SUBSTYPE_CHANNEL)
|
|
{
|
|
LPITEMIDLIST pidlFavs = NULL;
|
|
TCHAR tzFavsPath[MAX_PATH];
|
|
|
|
if (SUCCEEDED(SHGetSpecialFolderLocation(hwnd, CSIDL_FAVORITES, &pidlFavs))
|
|
&& SUCCEEDED(SHGetNameAndFlags(pidlFavs, SHGDN_FORPARSING | SHGDN_FORADDRESSBAR, tzFavsPath, SIZECHARS(tzFavsPath), NULL))
|
|
&& 0 == StrCmpNI(tzFavsPath, patf->pszInitDir, ARRAYSIZE(tzFavsPath)))
|
|
{
|
|
EnableWindow(pbffFavSubStruct->hwndNew, TRUE);
|
|
}
|
|
else
|
|
EnableWindow(pbffFavSubStruct->hwndNew, FALSE);
|
|
|
|
if(pidlFavs)
|
|
ILFree(pidlFavs);
|
|
}
|
|
else
|
|
EnableWindow(pbffFavSubStruct->hwndNew, TRUE);
|
|
|
|
int lRet = MLLoadString(IDS_FAVS_ADVANCED_COLLAPSE, szBuffer, ARRAYSIZE(szBuffer));
|
|
ASSERT(lRet);
|
|
}
|
|
SetWindowText(GetDlgItem(hwnd, IDC_FAVORITE_CREATEIN), szBuffer);
|
|
|
|
}
|
|
else
|
|
{
|
|
EndDialog(hwnd, IDCANCEL);
|
|
}
|
|
break;
|
|
}
|
|
case BFFM_SELCHANGED:
|
|
{
|
|
//the first of these comes during BFFM_INITIALIZED, so ignore it
|
|
if (((ADDTOFAV *)lpData)->pidlSelected != NULL)
|
|
{
|
|
ILFree(((ADDTOFAV *)lpData)->pidlSelected);
|
|
((ADDTOFAV *)lpData)->pidlSelected = ILClone((LPITEMIDLIST)lParam);
|
|
}
|
|
break;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
|
|
// This API is not exported. See below (DoAddToFavDlg) for the exported version
|
|
//
|
|
// hwnd parent window for the dialog.
|
|
// pszInitDir input: initial path
|
|
// output: fully qualified path and filename
|
|
// chInitDir Length of pszInitDir buffer
|
|
// pszFile initial (default) filename for shortcut
|
|
// cchFile Length of pszFile buffer
|
|
// pidlBrowse associated with pszInitDir
|
|
//
|
|
// Returns:
|
|
// TRUE if a directory and filename were selected by user, and no error
|
|
// occurs. In this case pszInitDir contains the new destination directory
|
|
// and filename, pszFile contains the new file name.
|
|
//
|
|
// FALSE if an error occurs or the user selects CANCEL.
|
|
|
|
STDAPI_(BOOL) DoAddToFavDlgEx(HWND hwnd,
|
|
TCHAR *pszInitDir, UINT cchInitDir,
|
|
TCHAR *pszFile, UINT cchFile,
|
|
LPITEMIDLIST pidlBrowse,
|
|
LPCITEMIDLIST pidlFavorite,
|
|
FAVDLGTYPE atfDlgType,
|
|
SUBSCRIPTIONINFO* pInfo)
|
|
{
|
|
ADDTOFAV atf = {pszInitDir, cchInitDir - 1, pszFile, cchFile - 1, pidlBrowse, NULL,
|
|
pidlFavorite, atfDlgType, {sizeof(SUBSCRIPTIONINFO), 0}, SUBSTYPE_URL };
|
|
TCHAR szTemp[1]; //NOTE: we're not using SHBrowseForFolder's prompt string (see below)
|
|
TCHAR szDisplayName[MAX_PATH];
|
|
BROWSEINFO bi = {
|
|
hwnd,
|
|
pidlBrowse,
|
|
szDisplayName,
|
|
szTemp,
|
|
BIF_RETURNONLYFSDIRS,
|
|
// (BFFCALLBACK)
|
|
BFFFavCallback,
|
|
(LPARAM)&atf,
|
|
0
|
|
};
|
|
LPITEMIDLIST pidl;
|
|
|
|
if (pInfo)
|
|
atf.siSubsInProg = *pInfo;
|
|
|
|
switch (atfDlgType)
|
|
{
|
|
case ATF_CHANNEL_SOFTDIST:
|
|
atf.bIsSoftdist = TRUE;
|
|
// fall through
|
|
case ATF_CHANNEL:
|
|
atf.subsType = SUBSTYPE_CHANNEL;
|
|
break;
|
|
|
|
//default:
|
|
// set in initialize to SUBSTYPE_URL
|
|
}
|
|
|
|
//this string is now in the template dialog in the .rc
|
|
//REVIEW -- do we want to do it this way (we're hiding SHBrowse...'s control)? then the template dialog looks more like the finished product...
|
|
szTemp[0] = 0;
|
|
|
|
//init native font control, otherwise dialog may fail to initialize
|
|
{
|
|
INITCOMMONCONTROLSEX icc;
|
|
|
|
icc.dwSize = sizeof(INITCOMMONCONTROLSEX);
|
|
icc.dwICC = ICC_NATIVEFNTCTL_CLASS;
|
|
InitCommonControlsEx(&icc);
|
|
}
|
|
|
|
pidl = SHBrowseForFolder(&bi);
|
|
|
|
if (pidl)
|
|
{
|
|
ILFree(pidl);
|
|
}
|
|
|
|
// If the user created a new subscription, start a download.
|
|
if (atf.bSubscribed && !atf.bStartSubscribed)
|
|
{
|
|
ISubscriptionMgr* pSubsMgr;
|
|
if (SUCCEEDED (CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISubscriptionMgr, (void**)&pSubsMgr)))
|
|
{
|
|
WCHAR wszURL[MAX_URL_STRING];
|
|
|
|
IEGetDisplayName(atf.pidlFavorite, wszURL, SHGDN_FORPARSING);
|
|
|
|
pSubsMgr->UpdateSubscription(wszURL);
|
|
pSubsMgr->Release();
|
|
}
|
|
}
|
|
|
|
return (pidl != NULL);
|
|
}
|
|
|
|
STDAPI_(BOOL) DoSafeAddToFavDlgEx(HWND hwnd,
|
|
TCHAR *pszInitDir, UINT cchInitDir,
|
|
TCHAR *pszFile, UINT cchFile,
|
|
LPITEMIDLIST pidlBrowse,
|
|
LPCITEMIDLIST pidlFavorite,
|
|
FAVDLGTYPE atfDlgType,
|
|
SUBSCRIPTIONINFO* pInfo)
|
|
{
|
|
BOOL fRet;
|
|
|
|
if (IEIsLinkSafe(hwnd, pidlFavorite, ILS_ADDTOFAV))
|
|
{
|
|
fRet = DoAddToFavDlgEx(hwnd, pszInitDir, cchInitDir, pszFile, cchFile,
|
|
pidlBrowse, pidlFavorite, atfDlgType, pInfo);
|
|
}
|
|
else
|
|
{
|
|
fRet = FALSE;
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
// This API is exported so that it may be called by explorer and mshtml (and MSNVIEWR.EXE)
|
|
// in addition to being called internally by shdocvw.
|
|
// THEREFORE YOU MUST NOT CHANGE THE SIGNATURE OF THIS API
|
|
//
|
|
|
|
STDAPI_(BOOL) DoAddToFavDlg(HWND hwnd,
|
|
CHAR *pszInitDir, UINT cchInitDir,
|
|
CHAR *pszFile, UINT cchFile,
|
|
LPITEMIDLIST pidlBrowse)
|
|
{
|
|
BOOL fRet;
|
|
|
|
WCHAR szInitDir[MAX_PATH];
|
|
WCHAR szFile[MAX_PATH];
|
|
|
|
SHAnsiToUnicode(pszInitDir, szInitDir, ARRAYSIZE(szInitDir));
|
|
SHAnsiToUnicode(pszFile, szFile, ARRAYSIZE(szFile));
|
|
|
|
fRet = DoSafeAddToFavDlgEx(hwnd, szInitDir, ARRAYSIZE(szInitDir), szFile, ARRAYSIZE(szFile), pidlBrowse, NULL, ATF_FAVORITE, NULL);
|
|
|
|
SHUnicodeToAnsi(szInitDir, pszInitDir, cchInitDir);
|
|
SHUnicodeToAnsi(szFile, pszFile, cchFile);
|
|
|
|
return fRet;
|
|
}
|
|
|
|
|
|
STDAPI_(BOOL) DoAddToFavDlgW(HWND hwnd,
|
|
WCHAR *pszInitDir, UINT cchInitDir,
|
|
WCHAR *pszFile, UINT cchFile,
|
|
LPITEMIDLIST pidlBrowse)
|
|
{
|
|
return DoSafeAddToFavDlgEx(hwnd, pszInitDir, cchInitDir, pszFile, cchFile, pidlBrowse, NULL, ATF_FAVORITE, NULL);
|
|
}
|
|
|
|
|
|
STDAPI AddToFavoritesEx(HWND hwnd, LPCITEMIDLIST pidlCur, LPCTSTR pszTitle, DWORD dwFlags,
|
|
SUBSCRIPTIONINFO *pInfo, IOleCommandTarget *pCommandTarget, IHTMLDocument2 *pDoc);
|
|
STDAPI AddToChannelsEx (HWND hwnd, LPCITEMIDLIST pidlUrl, LPTSTR pszName, LPCWSTR pwszURL,
|
|
DWORD dwFlags, SUBSCRIPTIONINFO* pInfo);
|
|
STDAPI SubscribeFromFavorites (HWND hwnd, LPCITEMIDLIST pidlUrl, LPTSTR pszName, DWORD dwFlags,
|
|
SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO *pInfo);
|
|
|
|
|
|
// This API is exported privately, and is called by ISubscriptionMgr::CreateSubscription.
|
|
// shuioc uses it too.
|
|
|
|
STDAPI SHAddSubscribeFavoriteEx (
|
|
HWND hwnd,
|
|
LPCWSTR pwszURL,
|
|
LPCWSTR pwszName,
|
|
DWORD dwFlags,
|
|
SUBSCRIPTIONTYPE subsType,
|
|
SUBSCRIPTIONINFO* pInfo,
|
|
IOleCommandTarget *pcmdt,
|
|
IHTMLDocument2 *pDoc)
|
|
{
|
|
TCHAR szName[MAX_PATH];
|
|
LPITEMIDLIST pidl = NULL;
|
|
HRESULT hr;
|
|
|
|
if (pwszURL==NULL || pwszName == NULL)
|
|
return E_INVALIDARG;
|
|
//
|
|
// Need to put pwszName into a buffer because it comes in const
|
|
// but gets modified in SubscribeFromFavorites.
|
|
//
|
|
hr = StringCchCopy(szName, ARRAYSIZE(szName), pwszName);
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
hr = IECreateFromPath(pwszURL, &pidl);
|
|
}
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
ASSERT (pidl);
|
|
|
|
if (dwFlags & CREATESUBS_FROMFAVORITES)
|
|
{
|
|
if (subsType != SUBSTYPE_URL && subsType != SUBSTYPE_CHANNEL)
|
|
{
|
|
ASSERT(0);
|
|
hr = E_INVALIDARG;
|
|
}
|
|
else
|
|
{
|
|
hr = SubscribeFromFavorites (hwnd, pidl, szName, dwFlags, subsType, pInfo);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
if (subsType == SUBSTYPE_URL)
|
|
{
|
|
hr = AddToFavoritesEx (hwnd, pidl, szName, dwFlags, pInfo, pcmdt, pDoc);
|
|
}
|
|
else if (subsType == SUBSTYPE_CHANNEL && !SHIsRestricted2W(hwnd, REST_NoChannelUI, NULL, 0))
|
|
{
|
|
hr = AddToChannelsEx (hwnd, pidl, szName, pwszURL, dwFlags, pInfo);
|
|
}
|
|
else
|
|
{
|
|
ASSERT (0);
|
|
hr = E_INVALIDARG;
|
|
}
|
|
}
|
|
|
|
ILFree(pidl);
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
STDAPI SHAddSubscribeFavorite (HWND hwnd, LPCWSTR pwszURL, LPCWSTR pwszName, DWORD dwFlags,
|
|
SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO* pInfo)
|
|
{
|
|
return SHAddSubscribeFavoriteEx ( hwnd, pwszURL, pwszName, dwFlags,
|
|
subsType, pInfo, NULL, NULL);
|
|
}
|
|
|
|
// this API is also exported via the .def
|
|
// Use for backward compatibility only -- note that it is only for URL's (not channels)
|
|
// and doesn't know how to subscribe.
|
|
STDAPI AddUrlToFavorites(HWND hwnd, LPWSTR pszUrlW, LPWSTR pszTitleW, BOOL fDisplayUI)
|
|
{
|
|
return SHAddSubscribeFavorite (hwnd, pszUrlW, pszTitleW,
|
|
fDisplayUI ? CREATESUBS_NOUI : 0, SUBSTYPE_URL, NULL);
|
|
}
|
|
|
|
|
|
// this API is in the .h and is used elsewhere in shdocvw, but is not exported
|
|
// Backward compatibility only -- only for URL's (not channels) and can subscribe, but can't
|
|
// pass in subscriptioninfo starter.
|
|
STDAPI AddToFavorites(
|
|
HWND hwnd,
|
|
LPCITEMIDLIST pidlCur,
|
|
LPCTSTR pszTitle,
|
|
BOOL fDisplayUI,
|
|
IOleCommandTarget *pCommandTarget,
|
|
IHTMLDocument2 *pDoc)
|
|
{
|
|
return AddToFavoritesEx (hwnd, pidlCur, pszTitle,
|
|
fDisplayUI ? 0 : CREATESUBS_NOUI, NULL, pCommandTarget, pDoc);
|
|
}
|
|
|
|
|
|
//helper function to create one column in a ListView control, add one item to that column,
|
|
//size the column to the width of the control, and color the control like a static...
|
|
//basically, like SetWindowText for a ListView. Because we use a lot of ListViews to display
|
|
//urls that would otherwise be truncated... the ListView gives us automatic ellipsis and ToolTip.
|
|
void SetListViewToString (HWND hLV, LPCTSTR pszString)
|
|
{
|
|
ASSERT(hLV);
|
|
|
|
LV_COLUMN lvc = {0};
|
|
RECT lvRect;
|
|
GetClientRect (hLV, &lvRect);
|
|
lvc.mask = LVCF_WIDTH;
|
|
lvc.cx = lvRect.right - lvRect.left;
|
|
if (-1 == ListView_InsertColumn(hLV, 0, &lvc)) {
|
|
ASSERT(0);
|
|
}
|
|
|
|
SendMessage(hLV, LVM_SETEXTENDEDLISTVIEWSTYLE, LVS_EX_INFOTIP, LVS_EX_INFOTIP);
|
|
|
|
LV_ITEM lvi = {0};
|
|
lvi.iSubItem = 0;
|
|
lvi.pszText = (LPTSTR)pszString;
|
|
lvi.mask = LVIF_TEXT;
|
|
ListView_InsertItem(hLV, &lvi);
|
|
ListView_EnsureVisible(hLV, 0, TRUE);
|
|
|
|
ListView_SetBkColor(hLV, GetSysColor(COLOR_BTNFACE));
|
|
ListView_SetTextBkColor(hLV, GetSysColor(COLOR_BTNFACE));
|
|
}
|
|
|
|
|
|
INT_PTR CALLBACK SubscribeFavoriteDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
ADDTOFAV * patf = (ADDTOFAV*)GetProp(hDlg, ADDTOFAVPROP);
|
|
|
|
switch (uMsg)
|
|
{
|
|
case WM_INITDIALOG:
|
|
{
|
|
TCHAR szURL[MAX_URL_STRING];
|
|
|
|
patf = (ADDTOFAV*)lParam;
|
|
SetProp(hDlg, ADDTOFAVPROP, (HANDLE)patf);
|
|
|
|
//set up name and url displays
|
|
SetDlgItemText (hDlg, IDC_CHANNEL_NAME, patf->pszFile);
|
|
//url is in patf->pidlFavorite
|
|
IEGetDisplayName(patf->pidlFavorite, szURL, SHGDN_FORPARSING);
|
|
SetListViewToString (GetDlgItem (hDlg, IDC_CHANNEL_URL), szURL);
|
|
|
|
//now the tricky part... this is for modifying the subscription associated with
|
|
//an existing ChannelBar shortcut. We need to find out if they are subscribed --
|
|
//if so, load the existing subscription into memory so it can be modified in the
|
|
//wizard. If not, leave the information that was passed up because it's got the
|
|
//schedule extracted from the CDF. In either case, check the radio button that
|
|
//corresponds to their current subscription level.
|
|
ISubscriptionMgr* pSubsMgr;
|
|
BOOL bSubs = FALSE;
|
|
|
|
HRESULT hr = JITCoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISubscriptionMgr, (void**)&pSubsMgr,
|
|
hDlg, FIEF_FLAG_FORCE_JITUI | FIEF_FLAG_PEEK);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
pSubsMgr->IsSubscribed(szURL, &bSubs);
|
|
|
|
patf->bStartSubscribed = bSubs;
|
|
|
|
pSubsMgr->Release();
|
|
}
|
|
else if ((E_ACCESSDENIED == hr) || !IsBrowserFrameOptionsPidlSet(patf->pidlFavorite, BFO_USE_IE_OFFLINE_SUPPORT))
|
|
{
|
|
EnableWindow(GetDlgItem(hDlg, IDC_MAKE_OFFLINE), FALSE);
|
|
}
|
|
|
|
if (!bSubs && patf->bIsSoftdist)
|
|
{
|
|
bSubs = TRUE;
|
|
}
|
|
|
|
CheckDlgButton(hDlg, IDC_MAKE_OFFLINE, bSubs ? 1 : 0);
|
|
EnableWindow(GetDlgItem (hDlg, IDC_SUBSCRIBE_CUSTOMIZE), bSubs);
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
RemoveProp (hDlg, ADDTOFAVPROP);
|
|
break;
|
|
|
|
case WM_HELP:
|
|
SHWinHelpOnDemandWrap((HWND)((LPHELPINFO) lParam)->hItemHandle, c_szHelpFile,
|
|
HELP_WM_HELP, (DWORD_PTR)(LPTSTR) (patf->iDlgType == ATF_FAVORITE
|
|
? aAddToFavHelpIDs : aAddToChanHelpIDs));
|
|
return TRUE;
|
|
break;
|
|
|
|
case WM_CONTEXTMENU:
|
|
SHWinHelpOnDemandWrap((HWND) wParam, c_szHelpFile, HELP_CONTEXTMENU,
|
|
(DWORD_PTR)(LPVOID) (patf->iDlgType == ATF_FAVORITE
|
|
? aAddToFavHelpIDs : aAddToChanHelpIDs));
|
|
return TRUE;
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
ASSERT (patf);
|
|
switch (GET_WM_COMMAND_ID(wParam, lParam))
|
|
{
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, IDCANCEL);
|
|
break;
|
|
|
|
case IDOK:
|
|
// first, make sure they're not trying to subscribe to an authenticated
|
|
// channel without entering a password.
|
|
if (SubscriptionFailsChannelAuthentication (hDlg, &patf->siSubsInProg))
|
|
return FALSE;
|
|
|
|
//find out whether they WERE subscribed, so if they click OK and they
|
|
//were already subscribed, we delete that subscription -- and either leave it
|
|
//deleted if "No subs" was the choice, or create the new one.
|
|
ISubscriptionMgr* pSubsMgr;
|
|
if (SUCCEEDED (JITCoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISubscriptionMgr, (void**)&pSubsMgr,
|
|
hDlg, FIEF_FLAG_FORCE_JITUI)))
|
|
{
|
|
//url is in patf->pidlFavorite
|
|
TCHAR szURL[MAX_URL_STRING];
|
|
IEGetDisplayName(patf->pidlFavorite, szURL, SHGDN_FORPARSING);
|
|
|
|
BOOL bAlreadySubs;
|
|
if (SUCCEEDED (pSubsMgr->IsSubscribed (szURL, &bAlreadySubs)) && bAlreadySubs)
|
|
{
|
|
pSubsMgr->DeleteSubscription(szURL, NULL);
|
|
}
|
|
|
|
pSubsMgr->Release();
|
|
}
|
|
|
|
if (IsDlgButtonChecked (hDlg, IDC_MAKE_OFFLINE))
|
|
{
|
|
//they want to subscribe! save subscription we already have in memory
|
|
patf->bSubscribed = StartSiteSubscription (hDlg, patf, TRUE);
|
|
}
|
|
EndDialog(hDlg, IDOK);
|
|
break;
|
|
|
|
// common code with ATF dialog
|
|
|
|
case IDC_SUBSCRIBE_CUSTOMIZE:
|
|
//need to create -- but not store -- subscription
|
|
//need to (temporarily) trash patf->pidlFavorite so that we can go through the
|
|
//wizard without colliding with an existing subscription. When we actually create
|
|
//the subscription, we'll use the real name.
|
|
LPCITEMIDLIST pidlSave = patf->pidlFavorite;
|
|
TCHAR szUrlTemp[MAX_URL_STRING+1];
|
|
IEGetDisplayName(patf->pidlFavorite, szUrlTemp, SHGDN_FORPARSING);
|
|
if(SUCCEEDED(StringCchCat(szUrlTemp, ARRAYSIZE(szUrlTemp), TEXT(".")))) //just put something nearly invisible on the end
|
|
{
|
|
if (SUCCEEDED (IECreateFromPath(szUrlTemp, (LPITEMIDLIST*)&patf->pidlFavorite)))
|
|
{
|
|
if (StartSiteSubscription (hDlg, patf, FALSE))
|
|
SendMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), TRUE);
|
|
ILFree ((LPITEMIDLIST)patf->pidlFavorite);
|
|
}
|
|
}
|
|
patf->pidlFavorite = pidlSave;
|
|
|
|
break;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
static const int CREATESUBS_ACTIVATE = 0x8000; //hidden flag meaning channel is already on system
|
|
|
|
STDAPI SubscribeFromFavorites (HWND hwnd, LPCITEMIDLIST pidlUrl, LPTSTR pszName, DWORD dwFlags,
|
|
SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO *pInfo)
|
|
{
|
|
//used to subscribe to a channel that's already in the Favorites
|
|
//or a URL that's already a Favorite
|
|
|
|
//flags are same as ISubscriptionMgr::CreateSubscription
|
|
|
|
//display our part of the fav's dialog -- no need to go through SHBrowseForFolder
|
|
//or any of that, just our radio buttons in a fixed-size dialog with our own DlgProc
|
|
|
|
INT_PTR iDlgResult;
|
|
HRESULT hr = S_OK;
|
|
ADDTOFAV atf = {0};
|
|
atf.pszFile = pszName;
|
|
atf.siSubsInProg.cbSize = sizeof(SUBSCRIPTIONINFO);
|
|
if (pInfo && pInfo->cbSize == sizeof(SUBSCRIPTIONINFO))
|
|
atf.siSubsInProg = *pInfo;
|
|
|
|
atf.subsType = subsType;
|
|
|
|
//figure out what dialog to use
|
|
atf.iDlgType = (subsType == SUBSTYPE_URL ? ATF_FAVORITE :
|
|
(dwFlags & CREATESUBS_ACTIVATE ? ATF_CHANNEL_MODIFY : ATF_CHANNEL));
|
|
// Do we potentially need ANOTHER dialog type for softdist channels?
|
|
|
|
if (dwFlags & CREATESUBS_SOFTWAREUPDATE)
|
|
{
|
|
atf.bIsSoftdist = TRUE;
|
|
}
|
|
|
|
atf.pidlFavorite = pidlUrl;
|
|
|
|
#ifdef OLD_FAVORITES
|
|
int iTemplate;
|
|
switch (atf.iDlgType)
|
|
{
|
|
case ATF_CHANNEL_SOFTDIST: // Inappropriate, but it doesn't currently get used
|
|
case ATF_CHANNEL:
|
|
iTemplate = IDD_SUBSCRIBE_FAV_CHANNEL;
|
|
break;
|
|
case ATF_CHANNEL_MODIFY:
|
|
iTemplate = IDD_ACTIVATE_PLATINUM_CHANNEL;
|
|
break;
|
|
case ATF_FAVORITE:
|
|
iTemplate = IDD_SUBSCRIBE_FAVORITE;
|
|
break;
|
|
}
|
|
|
|
iDlgResult = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(iTemplate), hwnd,
|
|
SubscribeFavoriteDlgProc, (LPARAM)&atf);
|
|
|
|
#endif
|
|
|
|
iDlgResult = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_ADDTOFAVORITES_TEMPLATE), hwnd,
|
|
SubscribeFavoriteDlgProc, (LPARAM)&atf);
|
|
|
|
|
|
switch (iDlgResult)
|
|
{
|
|
case -1:
|
|
hr = E_FAIL;
|
|
break;
|
|
case IDCANCEL:
|
|
hr = S_FALSE;
|
|
break;
|
|
default:
|
|
if (pInfo && (pInfo->cbSize == sizeof(SUBSCRIPTIONINFO))
|
|
&& (dwFlags & CREATESUBS_NOSAVE))
|
|
*pInfo = atf.siSubsInProg;
|
|
hr = S_OK;
|
|
break;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDAPI AddToChannelsEx (HWND hwnd, LPCITEMIDLIST pidlUrl, LPTSTR pszName, LPCWSTR pwszURL,
|
|
DWORD dwFlags, SUBSCRIPTIONINFO* pInfo)
|
|
{
|
|
HRESULT hr = S_OK;
|
|
IChannelMgrPriv* pIChannelMgrPriv;
|
|
|
|
hr = JITCoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER,
|
|
IID_IChannelMgrPriv, (void**)&pIChannelMgrPriv,
|
|
hwnd, FIEF_FLAG_FORCE_JITUI);
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
if (S_OK == pIChannelMgrPriv->IsChannelInstalled (pwszURL))
|
|
{
|
|
hr = SubscribeFromFavorites (hwnd, pidlUrl, pszName, dwFlags | CREATESUBS_ACTIVATE,
|
|
SUBSTYPE_CHANNEL, pInfo);
|
|
}
|
|
else
|
|
{
|
|
LPITEMIDLIST pidlChannelFolder;
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR szCFPath[MAX_PATH];
|
|
|
|
ASSERT(pIChannelMgrPriv);
|
|
|
|
IChannelMgrPriv::CHANNELFOLDERLOCATION cflLocation =
|
|
((dwFlags & CREATESUBS_SOFTWAREUPDATE) ?
|
|
IChannelMgrPriv::CF_SOFTWAREUPDATE :
|
|
IChannelMgrPriv::CF_CHANNEL);
|
|
|
|
hr = pIChannelMgrPriv->GetChannelFolder(&pidlChannelFolder, cflLocation);
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
//
|
|
// Change IChannelMgrPriv to unicode! This has to get fixed to
|
|
// support a unicode "Channels" name. (edwardp)
|
|
//
|
|
|
|
CHAR szBuff[MAX_PATH];
|
|
|
|
hr = pIChannelMgrPriv->GetChannelFolderPath (szBuff, ARRAYSIZE(szBuff), cflLocation);
|
|
|
|
if (SUCCEEDED(hr))
|
|
SHAnsiToUnicode(szBuff, szCFPath, ARRAYSIZE(szCFPath));
|
|
|
|
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
TCHAR szDspName[MAX_URL_STRING];
|
|
DWORD cchDspName = ARRAYSIZE(szDspName);
|
|
|
|
hr = StringCchCopy(szPath, ARRAYSIZE(szPath), szCFPath);
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
// When we create a short cut for the URL, we have to make sure it's readable for
|
|
// the end user. PrepareURLForDisplay() will unescape the string if it's escaped.
|
|
if (!UrlIs(pszName, URLIS_URL) ||
|
|
!PrepareURLForDisplay(pszName, szDspName, &cchDspName))
|
|
{
|
|
// Unescaping wasn't wanted or didn't work.
|
|
hr = StringCchCopy(szDspName, ARRAYSIZE(szDspName), pszName);
|
|
}
|
|
}
|
|
|
|
if(SUCCEEDED(hr))
|
|
{
|
|
PathCleanupSpec(szPath, szDspName);
|
|
|
|
FAVDLGTYPE iDlgType = (dwFlags & CREATESUBS_SOFTWAREUPDATE ? ATF_CHANNEL_SOFTDIST : ATF_CHANNEL);
|
|
|
|
if ((dwFlags & CREATESUBS_NOUI) ||
|
|
DoSafeAddToFavDlgEx(hwnd, szPath, ARRAYSIZE(szPath),
|
|
szDspName, ARRAYSIZE(szDspName), pidlChannelFolder,
|
|
pidlUrl, iDlgType, pInfo))
|
|
{
|
|
//we create the channelbar entry here, instead of cdfview, because here
|
|
//we know where in the channels folder the user wants it to go.
|
|
IChannelMgr* pChannelMgr = NULL;
|
|
hr = pIChannelMgrPriv->QueryInterface (IID_IChannelMgr, (void**)&pChannelMgr);
|
|
if (SUCCEEDED (hr))
|
|
{
|
|
//prepare strings
|
|
PathRemoveExtension(szPath);
|
|
|
|
//strip off absolute part of folder path, and convert to Unicode
|
|
int cchCommon = PathCommonPrefix (szPath, szCFPath, NULL);
|
|
|
|
//pack in the info we have
|
|
CHANNELSHORTCUTINFO csiChannel = {0};
|
|
csiChannel.cbSize = sizeof(csiChannel);
|
|
csiChannel.pszTitle = szPath + cchCommon;
|
|
csiChannel.pszURL = (LPWSTR)pwszURL;
|
|
csiChannel.bIsSoftware = (dwFlags & CREATESUBS_SOFTWAREUPDATE) ? TRUE : FALSE;
|
|
//and tell the channel mgr to add the channel
|
|
hr = pChannelMgr->AddChannelShortcut (&csiChannel);
|
|
pChannelMgr->Release();
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = S_FALSE; //no failure, but no add
|
|
}
|
|
}
|
|
}
|
|
|
|
ILFree (pidlChannelFolder);
|
|
}
|
|
}
|
|
pIChannelMgrPriv->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
STDAPI AddToFavoritesEx(
|
|
HWND hwnd,
|
|
LPCITEMIDLIST pidlCur,
|
|
LPCTSTR pszTitle,
|
|
DWORD dwFlags,
|
|
SUBSCRIPTIONINFO *pInfo,
|
|
IOleCommandTarget *pCommandTarget,
|
|
IHTMLDocument2 *pDoc)
|
|
{
|
|
HRESULT hres = S_FALSE;
|
|
HRESULT hr;
|
|
HCURSOR hCursorOld = SetCursor(LoadCursor(NULL, IDC_WAIT));
|
|
|
|
if (pidlCur)
|
|
{
|
|
TCHAR szName[MAX_URL_STRING];
|
|
TCHAR szPath[MAX_PATH];
|
|
if (pszTitle)
|
|
{
|
|
hr = StringCchCopy(szName, ARRAYSIZE(szName), pszTitle);
|
|
if(FAILED (hr))
|
|
{
|
|
SetCursor(hCursorOld);
|
|
return hr;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
szName[0] = 0;
|
|
|
|
IEGetNameAndFlags(pidlCur, SHGDN_INFOLDER | SHGDN_NORMAL, szName, SIZECHARS(szName), NULL);
|
|
}
|
|
|
|
LPITEMIDLIST pidlFavorites;
|
|
|
|
if (SHGetSpecialFolderPath(NULL, szPath, CSIDL_FAVORITES, TRUE) &&
|
|
(pidlFavorites = SHCloneSpecialIDList(NULL, CSIDL_FAVORITES, TRUE)))
|
|
{
|
|
TCHAR szDspName[MAX_PATH];
|
|
DWORD cchDspName = ARRAYSIZE(szDspName);
|
|
|
|
// When we create a short cut for the URL, we have to make sure it's readable for
|
|
// the end user. PrepareURLForDisplay() will unescape the string if it's escaped.
|
|
if (!UrlIs(szName, URLIS_URL) ||
|
|
!PrepareURLForDisplay(szName, szDspName, &cchDspName))
|
|
{
|
|
// Unescaping wasn't wanted or didn't work.
|
|
hr = StringCchCopy(szDspName, ARRAYSIZE(szDspName), szName);
|
|
if(FAILED(hr))
|
|
{
|
|
ILFree(pidlFavorites);
|
|
SetCursor(hCursorOld);
|
|
return hr;
|
|
}
|
|
}
|
|
|
|
PathCleanupSpec(szPath, szDspName);
|
|
|
|
// if left with spaces only, use the filename friendly version of the url instead.
|
|
StrTrim(szDspName, L" ");
|
|
if (szDspName[0] == 0)
|
|
{
|
|
if (SUCCEEDED(IEGetNameAndFlags(pidlCur, SHGDN_FORPARSING, szDspName, ARRAYSIZE(szDspName), NULL)))
|
|
PathCleanupSpec(szPath, szDspName);
|
|
}
|
|
|
|
BOOL fDisplayUI = (dwFlags & CREATESUBS_NOUI) ? FALSE : TRUE;
|
|
if (!fDisplayUI ||
|
|
DoSafeAddToFavDlgEx(hwnd, szPath, ARRAYSIZE(szPath),
|
|
szDspName, ARRAYSIZE(szDspName), pidlFavorites,
|
|
pidlCur, ATF_FAVORITE, NULL))
|
|
{
|
|
if (fDisplayUI)
|
|
PathRemoveFileSpec(szPath);
|
|
|
|
ISHCUT_PARAMS ShCutParams = {0};
|
|
|
|
PathRemoveExtension(szDspName);
|
|
|
|
ShCutParams.pidlTarget = pidlCur;
|
|
ShCutParams.pszTitle = PathFindFileName(szDspName);
|
|
ShCutParams.pszDir = szPath;
|
|
ShCutParams.pszOut = NULL;
|
|
ShCutParams.bUpdateProperties = FALSE;
|
|
ShCutParams.bUniqueName = FALSE;
|
|
ShCutParams.bUpdateIcon = TRUE;
|
|
ShCutParams.pCommand = pCommandTarget;
|
|
ShCutParams.pDoc = pDoc;
|
|
hres = CreateShortcutInDirEx(&ShCutParams);
|
|
if (fDisplayUI && FAILED(hres))
|
|
{
|
|
IE_ErrorMsgBox(NULL, hwnd, GetLastError(), NULL, szDspName, IDS_FAV_UNABLETOCREATE, MB_OK| MB_ICONSTOP);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hres = S_FALSE;
|
|
}
|
|
ILFree(pidlFavorites);
|
|
}
|
|
}
|
|
|
|
SetCursor(hCursorOld);
|
|
|
|
return hres;
|
|
}
|
|
|
|
|
|
BOOL IsSubscribed(ADDTOFAV *patf)
|
|
{
|
|
BOOL bSubscribed = FALSE;
|
|
|
|
TCHAR szURL[MAX_URL_STRING];
|
|
if (SUCCEEDED(IEGetDisplayName(patf->pidlFavorite, szURL, SHGDN_FORPARSING)))
|
|
{
|
|
ISubscriptionMgr *pSubscriptionMgr;
|
|
if (SUCCEEDED(CoCreateInstance(CLSID_SubscriptionMgr,
|
|
NULL, CLSCTX_INPROC_SERVER,
|
|
IID_ISubscriptionMgr,
|
|
(void**)&pSubscriptionMgr)))
|
|
{
|
|
BSTR bstrURL = SysAllocStringT(szURL);
|
|
if (bstrURL)
|
|
{
|
|
if (SUCCEEDED(pSubscriptionMgr->IsSubscribed(bstrURL, &bSubscribed)) &&
|
|
bSubscribed)
|
|
{
|
|
patf->siSubsInProg.fUpdateFlags = SUBSINFO_ALLFLAGS;
|
|
pSubscriptionMgr->GetSubscriptionInfo(bstrURL, &patf->siSubsInProg);
|
|
}
|
|
SysFreeString(bstrURL);
|
|
}
|
|
pSubscriptionMgr->Release();
|
|
}
|
|
}
|
|
|
|
return bSubscribed;
|
|
}
|
|
|
|
BOOL IsSubscribed(LPWSTR pwzUrl)
|
|
{
|
|
#ifndef DISABLE_SUBSCRIPTIONS
|
|
|
|
BOOL bSubscribed = FALSE;
|
|
|
|
ISubscriptionMgr * pSubscriptionMgr;
|
|
if (FAILED(CoCreateInstance(CLSID_SubscriptionMgr,
|
|
NULL,
|
|
CLSCTX_INPROC_SERVER,
|
|
IID_ISubscriptionMgr,
|
|
(void**)&pSubscriptionMgr)))
|
|
{
|
|
return FALSE;
|
|
}
|
|
|
|
pSubscriptionMgr->IsSubscribed(pwzUrl, &bSubscribed);
|
|
pSubscriptionMgr->Release();
|
|
|
|
return bSubscribed;
|
|
|
|
#else /* !DISABLE_SUBSCRIPTIONS */
|
|
|
|
return FALSE;
|
|
|
|
#endif /* !DISABLE_SUBSCRIPTIONS */
|
|
}
|