|
|
#include "private.h"
#include "subsmgrp.h"
#include "offl_cpp.h"
#include "helper.h"
#include "propshts.h"
#include "apithk.h"
#include <mluisupp.h>
#undef TF_THISMODULE
#define TF_THISMODULE TF_WEBCHECKCORE
extern HRESULT LoadSubscription(LPCTSTR url, LPMYPIDL *); extern TCHAR szInternetSettings[];
extern void PropagateGeneralProp(HWND, POOEBuf); extern INT_PTR CALLBACK EnableScreenSaverDlgProc(HWND, UINT, WPARAM, LPARAM); extern HRESULT CreateSubscriptionFromOOEBuf(POOEBuf, LPMYPIDL *);
extern BOOL CALLBACK _AddOnePropSheetPage(HPROPSHEETPAGE, LPARAM);
extern TCHAR g_szDontAskScreenSaver[]; // from WIZARDS.CPP
#define MAX_STR_LENGTH 200
extern DWORD aHelpIDs[]; extern TCHAR c_szHelpFile[];
typedef struct { CSubscriptionMgr* pMgr; LPCWSTR pwszName; LPCWSTR pwszUrl; SUBSCRIPTIONINFO* pSubsInfo; SUBSCRIPTIONTYPE subsType; DWORD dwFlags; } SUBSCRIBE_ADI_INFO;
static const TCHAR SUBSCRIBEADIPROP[] = TEXT("SADIP");
INT_PTR CALLBACK SummarizeDesktopSubscriptionDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
////////////////////////////////////////////////////////////////////////////////
// Private imports from shdocvw (AddToFavorites API)
//
STDAPI SHAddSubscribeFavorite (HWND hwnd, LPCWSTR pwszURL, LPCWSTR pwszName, DWORD dwFlags, SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO* pInfo); ////////////////////////////////////////////////////////////////////////////////
void UpdateSubsInfoFromOOE (SUBSCRIPTIONINFO* pInfo, POOEBuf pooe);
HRESULT CreateBSTRFromTSTR(BSTR * pBstr, LPCTSTR sz) { int i = lstrlen(sz) + 1; *pBstr = SysAllocStringLen(NULL, i); if(NULL == *pBstr) return E_OUTOFMEMORY;
MyStrToOleStrN(*pBstr, i, sz); return S_OK; }
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Subsctiption Manager
//
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// constructor / destructor
//
CSubscriptionMgr::CSubscriptionMgr(void) { ASSERT(NULL == _pidl);
m_cRef = 1; m_eInitSrc = _INIT_FROM_URL; // Default.
m_oldType = SUBSTYPE_URL; // Default.
DllAddRef(); }
CSubscriptionMgr::~CSubscriptionMgr() { if (_pidl) { COfflineFolderEnum::FreePidl(_pidl); _pidl = NULL; } SAFELOCALFREE(m_pBuf); SAFERELEASE(m_pUIHelper); DllRelease(); }
//
// IUnknown members
//
STDMETHODIMP CSubscriptionMgr::QueryInterface(REFIID riid, void ** ppv) { *ppv=NULL;
// Validate requested interface
if ((IID_IUnknown == riid) || (IID_ISubscriptionMgr == riid) || (IID_ISubscriptionMgr2 == riid)) { *ppv=(ISubscriptionMgr2 *)this; } else if(IID_ISubscriptionMgrPriv == riid) { *ppv=(ISubscriptionMgrPriv *)this; } else if(IID_IShellExtInit == riid) { *ppv=(IShellExtInit *)this; } else if(IID_IShellPropSheetExt == riid) { *ppv=(IShellPropSheetExt *)this; } else { return E_NOINTERFACE; }
((LPUNKNOWN)*ppv)->AddRef(); return S_OK; }
STDMETHODIMP_(ULONG) CSubscriptionMgr::AddRef(void) { return ++m_cRef; }
STDMETHODIMP_(ULONG) CSubscriptionMgr::Release(void) { if( 0L != --m_cRef ) return m_cRef;
delete this; return 0L; }
HRESULT CSubscriptionMgr::RemovePages(HWND hDlg) { HRESULT hr;
ASSERT(NULL != m_pUIHelper);
if (NULL == m_pUIHelper) { return E_UNEXPECTED; }
ISubscriptionAgentShellExt *psase;
hr = m_pUIHelper->QueryInterface(IID_ISubscriptionAgentShellExt, (void **)&psase);
if (SUCCEEDED(hr)) { hr = psase->RemovePages(hDlg); psase->Release(); }
return hr; }
HRESULT CSubscriptionMgr::SaveSubscription() { HRESULT hr;
ASSERT(NULL != m_pUIHelper);
if (NULL == m_pUIHelper) { return E_UNEXPECTED; }
DWORD dwMaxCount = SHRestricted2W(REST_MaxSubscriptionCount, NULL, 0); DWORD dwCount; SUBSCRIPTIONTYPE subsType = (m_eInitSrc == _INIT_FROM_INTSHCUT) ? SUBSTYPE_URL : SUBSTYPE_CHANNEL; if ((dwMaxCount > 0) && SUCCEEDED(CountSubscriptions(subsType, &dwCount)) && (dwCount >= dwMaxCount)) { SGMessageBox(GetForegroundWindow(), IDS_RESTRICTED, MB_OK); return E_ACCESSDENIED; } ISubscriptionAgentShellExt *psase;
hr = m_pUIHelper->QueryInterface(IID_ISubscriptionAgentShellExt, (void **)&psase);
if (SUCCEEDED(hr)) { hr = psase->SaveSubscription(); psase->Release(); }
return hr; }
HRESULT CSubscriptionMgr::URLChange(LPCWSTR pwszNewURL) { return E_NOTIMPL; }
HRESULT GetInfoFromDataObject(IDataObject *pido, TCHAR *pszPath, DWORD cchPath, TCHAR *pszFriendlyName, DWORD cchFriendlyName, TCHAR *pszURL, DWORD cchURL, INIT_SRC_ENUM *peInitSrc) { STGMEDIUM stgmed; FORMATETC fmtetc = { CF_HDROP, NULL, DVASPECT_CONTENT, -1, TYMED_HGLOBAL }; HRESULT hr = pido->GetData(&fmtetc, &stgmed);
if (hr == S_OK) { TCHAR szTempURL[INTERNET_MAX_URL_LENGTH]; TCHAR *pszSection; TCHAR *pszEntry; TCHAR szTempPath[MAX_PATH]; TCHAR szIniPath[MAX_PATH];
if (DragQueryFile((HDROP)stgmed.hGlobal, 0, szTempPath, ARRAYSIZE(szTempPath))) { // save path
if (NULL != pszPath) { StrCpyN(pszPath, szTempPath, cchPath); }
StrCpyN(szIniPath, szTempPath, ARRAYSIZE(szIniPath)); // make friendly name from path
if (NULL != pszFriendlyName) { PathStripPath(szTempPath); PathRemoveExtension(szTempPath); StrCpyN(pszFriendlyName, szTempPath, cchFriendlyName); }
if ((NULL != pszURL) || (NULL != peInitSrc)) {
if (PathIsDirectory(szIniPath)) { PathAppend(szIniPath, TEXT("desktop.ini")); pszSection = TEXT("Channel"); pszEntry = TEXT("CDFURL");
if (NULL != peInitSrc) *peInitSrc = _INIT_FROM_CHANNEL; } else { pszSection = TEXT("InternetShortcut"); pszEntry = TEXT("URL"); if (NULL != peInitSrc) *peInitSrc = _INIT_FROM_INTSHCUT; }
if (NULL != pszURL) { // canonicalize url
if (SHGetIniString(pszSection, pszEntry, szTempURL, INTERNET_MAX_URL_LENGTH, szIniPath)) { if(!InternetCanonicalizeUrl(szTempURL, pszURL, &cchURL, ICU_NO_ENCODE)) { // failed - use non-canonical version
StrCpyN(pszURL, szTempURL, cchURL); } } else { hr = E_FAIL; } } } } else { hr = E_FAIL; }
ReleaseStgMedium(&stgmed); }
return hr; }
//
// IShellExtInit / IShellPropSheetExt members
//
STDMETHODIMP CSubscriptionMgr::Initialize(LPCITEMIDLIST pcidlFolder, IDataObject * pido, HKEY hkeyProgID) { HRESULT hr; ISubscriptionItem *psi; CLSID clsid; SUBSCRIPTIONCOOKIE cookie;
hr = GetInfoFromDataObject(pido, m_pszPath, ARRAYSIZE(m_pszPath), m_pszFriendly, ARRAYSIZE(m_pszFriendly), m_pszURL, ARRAYSIZE(m_pszURL), &m_eInitSrc);
if (SUCCEEDED(hr)) { hr = DoGetItemFromURL(m_pszURL, &psi); if (SUCCEEDED(hr)) { SUBSCRIPTIONITEMINFO sii;
sii.cbSize = sizeof(SUBSCRIPTIONITEMINFO);
hr = psi->GetSubscriptionItemInfo(&sii);
if (SUCCEEDED(hr)) { clsid = sii.clsidAgent; }
psi->GetCookie(&cookie);
psi->Release(); }
if (FAILED(hr)) { // New subscription
hr = S_OK; CreateCookie(&cookie);
switch (m_eInitSrc) { case _INIT_FROM_INTSHCUT: clsid = CLSID_WebCrawlerAgent; break; case _INIT_FROM_CHANNEL: clsid = CLSID_ChannelAgent; break;
default: hr = E_FAIL; break; } }
if (SUCCEEDED(hr)) { // HACKHACK:
// We call coinit and uninit and keep an object pointer around.
// This ain't cool but will work as long as the agents are in
// webcheck. Need to fix this for multi-cast handler.
hr = CoInitialize(NULL);
if (SUCCEEDED(hr)) { hr = CoCreateInstance(clsid, NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void**)&m_pUIHelper);
if (SUCCEEDED(hr)) { ISubscriptionAgentShellExt *psase;
hr = m_pUIHelper->QueryInterface(IID_ISubscriptionAgentShellExt, (void **)&psase); if (SUCCEEDED(hr)) { WCHAR wszURL[ARRAYSIZE(m_pszURL)]; WCHAR wszName[MAX_NAME + 1];
MyStrToOleStrN(wszURL, ARRAYSIZE(wszURL), m_pszURL); MyStrToOleStrN(wszName, ARRAYSIZE(wszName), m_pszFriendly); hr = psase->Initialize(&cookie, wszURL, wszName, (clsid == CLSID_ChannelAgent) ? SUBSTYPE_CHANNEL : SUBSTYPE_URL); psase->Release(); } } CoUninitialize(); } } }
return hr; }
STDMETHODIMP CSubscriptionMgr::AddPages(LPFNADDPROPSHEETPAGE lpfnAddPage, LPARAM lParam) { HRESULT hr; if (SHRestricted2W(REST_NoEditingSubscriptions, NULL, 0)) return E_FAIL;
ASSERT(NULL != m_pUIHelper);
if (NULL == m_pUIHelper) { return E_UNEXPECTED; }
IShellPropSheetExt *pspse;
hr = m_pUIHelper->QueryInterface(IID_IShellPropSheetExt, (void **)&pspse);
if (SUCCEEDED(hr)) { hr = pspse->AddPages(lpfnAddPage, lParam); pspse->Release(); }
return hr; }
STDMETHODIMP CSubscriptionMgr::ReplacePage(UINT uPageID, LPFNADDPROPSHEETPAGE lpfnReplacePage, LPARAM lParam) { return E_NOTIMPL; }
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// ISubscriptionMgr members
//
STDMETHODIMP CSubscriptionMgr::IsSubscribed(LPCWSTR pURL, BOOL * pFSub) { HRESULT hr;
ASSERT (pURL && pFSub); MyOleStrToStrN(m_pszURL, INTERNET_MAX_URL_LENGTH, pURL); * pFSub = FALSE;
if (!_pidl) { hr = LoadSubscription(m_pszURL, &_pidl); if ((hr != S_OK) || (!_pidl)) return S_OK; } else if (UrlCompare(URL(&(_pidl->ooe)), m_pszURL, TRUE)) { COfflineFolderEnum::FreePidl(_pidl); _pidl = NULL; hr = LoadSubscription(m_pszURL, &_pidl); if ((hr != S_OK) || (!_pidl)) return S_OK; }
* pFSub = TRUE; return S_OK; }
STDMETHODIMP CSubscriptionMgr::DeleteSubscription(LPCWSTR pURL, HWND hwnd) { ASSERT(pURL); MyOleStrToStrN(m_pszURL, INTERNET_MAX_URL_LENGTH, pURL);
if (!_pidl) { HRESULT hr;
hr = LoadSubscription(m_pszURL, &_pidl); if ((hr != S_OK) || (!_pidl)) return E_FAIL; }
// This is a restricted action. The restriction
// is checked in ConfirmDelete. If you remove this call,
// you must add the restriction check here.
if (!ConfirmDelete(hwnd, 1, &_pidl)) return E_FAIL;
HRESULT hr = DoDeleteSubscription(&(_pidl->ooe)); if (SUCCEEDED(hr)) { TraceMsg(TF_ALWAYS, "%s(URL:%s) deleted", NAME(&(_pidl->ooe)), URL(&(_pidl->ooe)));
_GenerateEvent(SHCNE_DELETE, (LPITEMIDLIST)_pidl, NULL);
COfflineFolderEnum::FreePidl(_pidl); _pidl = NULL; } return hr; }
STDMETHODIMP CSubscriptionMgr::ShowSubscriptionProperties(LPCWSTR pURL, HWND hwnd) { HRESULT hr = S_OK; LPMYPIDL oldPidl = NULL, newPidl = NULL;
ASSERT(pURL); MyOleStrToStrN(m_pszURL, INTERNET_MAX_URL_LENGTH, pURL);
if (!m_pBuf) { m_pBuf = (OOEBuf *)MemAlloc(LPTR, sizeof(OOEBuf)); if (NULL == m_pBuf) { hr = E_OUTOFMEMORY; } }
if (SUCCEEDED(hr)) { GetDefaultOOEBuf(m_pBuf, SUBSTYPE_URL);
if(SUCCEEDED(LoadSubscription(m_pszURL, &oldPidl))) { POOEntry pooe = &(oldPidl->ooe);
StrCpyN(m_pszFriendly, NAME(&(oldPidl->ooe)), ARRAYSIZE(m_pszFriendly));
CopyToOOEBuf(&(oldPidl->ooe), m_pBuf);
m_pBuf->m_dwPropSheetFlags = PSF_IS_ALREADY_SUBSCRIBED; } else { CreateCookie(&m_pBuf->m_Cookie); StrCpyN(m_pszFriendly, m_pszURL, ARRAYSIZE(m_pszFriendly)); StrCpyN(m_pBuf->m_URL, m_pszURL, ARRAYSIZE(m_pBuf->m_URL)); StrCpyN(m_pBuf->m_Name, m_pszURL, ARRAYSIZE(m_pBuf->m_Name)); }
hr = CoCreateInstance(*(&m_pBuf->clsidDest), NULL, CLSCTX_INPROC_SERVER, IID_IUnknown, (void **)&m_pUIHelper);
if (SUCCEEDED(hr)) { ISubscriptionAgentShellExt *psase; hr = m_pUIHelper->QueryInterface(IID_ISubscriptionAgentShellExt, (void **)&psase);
if (SUCCEEDED(hr)) { WCHAR wszURL[MAX_URL + 1]; WCHAR wszName[MAX_NAME + 1];
MyStrToOleStrN(wszURL, ARRAYSIZE(wszURL), m_pBuf->m_URL); MyStrToOleStrN(wszName, ARRAYSIZE(wszName), m_pBuf->m_Name);
hr = psase->Initialize(&m_pBuf->m_Cookie, wszURL, wszName, (SUBSCRIPTIONTYPE)-1); psase->Release(); }
if (SUCCEEDED(hr)) { PROPSHEETHEADER psh = { 0 } ; HPROPSHEETPAGE hPropPage[MAX_PROP_PAGES];
// initialize propsheet header.
psh.dwSize = sizeof(PROPSHEETHEADER); psh.dwFlags = PSH_PROPTITLE; psh.hwndParent = hwnd; psh.pszCaption = m_pszFriendly; psh.hInstance = g_hInst; psh.nPages = 0; psh.nStartPage = 0; psh.phpage = hPropPage;
PROPSHEETPAGE psp; psp.dwSize = sizeof(PROPSHEETPAGE); psp.dwFlags = PSP_DEFAULT; psp.hInstance = MLGetHinst(); psp.pszIcon = NULL; psp.pszTitle = NULL; psp.lParam = (LPARAM)this;
psp.pszTemplate = MAKEINTRESOURCE(IDD_SUBSPROPS_SUMMARY); psp.pfnDlgProc = SummaryPropDlgProc;
psh.phpage[psh.nPages++] = Whistler_CreatePropertySheetPageW(&psp);
if (NULL != hPropPage[0]) { if (m_pBuf->m_dwPropSheetFlags & PSF_IS_ALREADY_SUBSCRIBED) { hr = AddPages(_AddOnePropSheetPage, (LPARAM)&psh); }
if (SUCCEEDED(hr)) { INT_PTR iRet = PropertySheet(&psh);
if (iRet < 0) { hr = E_FAIL; } else { hr = LoadSubscription(m_pszURL, &newPidl); if (SUCCEEDED(hr)) { if (_pidl) { COfflineFolderEnum::FreePidl(_pidl); }
_pidl = newPidl; } } } } } }
if (NULL != oldPidl) { COfflineFolderEnum::FreePidl(oldPidl); } }
return hr; }
//
//
//
void CSubscriptionMgr::ChangeSubscriptionValues ( OOEBuf *pCurrent, SUBSCRIPTIONINFO *pNew ) { //
// Channel flags
//
if (SUBSINFO_CHANNELFLAGS & pNew->fUpdateFlags) { pCurrent->fChannelFlags = pNew->fChannelFlags; }
//
// The subscription schedule.
//
if (SUBSINFO_SCHEDULE & pNew->fUpdateFlags) {
switch (pNew->schedule) {
case SUBSSCHED_DAILY: case SUBSSCHED_MANUAL: case SUBSSCHED_WEEKLY: LoadGroupCookie(&pCurrent->groupCookie, pNew->schedule); break;
case SUBSSCHED_CUSTOM: pCurrent->groupCookie = pNew->customGroupCookie; break;
case SUBSSCHED_AUTO: { // FEATURE. We should look at subType;
memset(&pCurrent->groupCookie, 0, sizeof(pCurrent->groupCookie)); //t-mattgi so it will look at the trigger
PTASK_TRIGGER pNewTrigger = ((PTASK_TRIGGER)pNew->pTrigger); if (pNewTrigger && pNewTrigger->cbTriggerSize == sizeof(TASK_TRIGGER)) { pCurrent->m_Trigger = *pNewTrigger; } else //bad trigger; use daily as default
{ pCurrent->m_Trigger.cbTriggerSize = 0; pCurrent->groupCookie = NOTFCOOKIE_SCHEDULE_GROUP_DAILY; } } pCurrent->fChannelFlags |= CHANNEL_AGENT_DYNAMIC_SCHEDULE; break;
default: ASSERT(FALSE); break; } }
//
// Recurse levels.
//
if (SUBSINFO_RECURSE & pNew->fUpdateFlags) pCurrent->m_RecurseLevels = pNew->dwRecurseLevels;
//
// Webcrawler flags. Note: The flags are not or'd with the current flags.
// The caller must set all of the webcrawler flags they want to use.
//
if (SUBSINFO_WEBCRAWL & pNew->fUpdateFlags) pCurrent->m_RecurseFlags = pNew->fWebcrawlerFlags;
//
// Mail notification.
//
if (SUBSINFO_MAILNOT & pNew->fUpdateFlags) pCurrent->bMail = pNew->bMailNotification; else pCurrent->bMail = FALSE;
//
// Need password.
//
if (SUBSINFO_NEEDPASSWORD & pNew->fUpdateFlags) pCurrent->bNeedPassword = pNew->bNeedPassword; else pCurrent->bNeedPassword = FALSE; //
// User name.
//
if (SUBSINFO_USER & pNew->fUpdateFlags) { if (pNew->bstrUserName) { MyOleStrToStrN(pCurrent->username, MAX_USERNAME, pNew->bstrUserName); } pCurrent->bNeedPassword = pNew->bNeedPassword; } //
// Password.
//
if (SUBSINFO_PASSWORD & pNew->fUpdateFlags) { if (pNew->bstrPassword) { MyOleStrToStrN(pCurrent->password, MAX_PASSWORD, pNew->bstrPassword); } pCurrent->bNeedPassword = pNew->bNeedPassword; }
//
// Friendly Name.
//
if (SUBSINFO_FRIENDLYNAME & pNew->fUpdateFlags) { if (pNew->bstrFriendlyName) { MyOleStrToStrN(pCurrent->m_Name, MAX_NAME, pNew->bstrFriendlyName); } }
//
// Gleam
//
if (SUBSINFO_GLEAM & pNew->fUpdateFlags) { pCurrent->bGleam = pNew->bGleam; }
//
// Changes only (notification only)
//
if (SUBSINFO_CHANGESONLY & pNew->fUpdateFlags) { pCurrent->bChangesOnly = pNew->bChangesOnly; }
//
// dwMaxSizeKB
//
if (SUBSINFO_MAXSIZEKB & pNew->fUpdateFlags) { pCurrent->m_SizeLimit = pNew->dwMaxSizeKB; }
//
// Task flags
//
if (SUBSINFO_TASKFLAGS & pNew->fUpdateFlags) { pCurrent->grfTaskTrigger = pNew->fTaskFlags; }
return; }
//
// CSubscriptionMgr::CountSubscriptions
// FEATURE: We could make this public if other people need it. An enumerator
// would be more useful though...
//
HRESULT CSubscriptionMgr::CountSubscriptions(SUBSCRIPTIONTYPE subType, PDWORD pdwCount) { HRESULT hr; IEnumSubscription *pes;
ASSERT(NULL != pdwCount);
*pdwCount = 0;
hr = EnumSubscriptions(0, &pes);
if (SUCCEEDED(hr)) { SUBSCRIPTIONCOOKIE cookie;
while (S_OK == pes->Next(1, &cookie, NULL)) { ISubscriptionItem *psi; DWORD dwRet;
if (SUCCEEDED(SubscriptionItemFromCookie(FALSE, &cookie, &psi))) { if (SUCCEEDED(ReadDWORD(psi, c_szPropChannel, &dwRet)) && dwRet) { if (SUBSTYPE_CHANNEL == subType) (*pdwCount)++; } else if (SUCCEEDED(ReadDWORD(psi, c_szPropDesktopComponent, &dwRet)) && dwRet) { if (SUBSTYPE_DESKTOPURL == subType || SUBSTYPE_DESKTOPCHANNEL == subType) (*pdwCount)++; } else { if (SUBSTYPE_URL == subType) (*pdwCount)++; } psi->Release(); } } }
return hr; }
//
// CSubscriptionMgr::IsValidSubscriptionInfo
//
#define SUBSCRIPTIONSCHEDULE_MAX 4
BOOL CSubscriptionMgr::IsValidSubscriptionInfo(SUBSCRIPTIONTYPE subType, SUBSCRIPTIONINFO *pSI) { if (pSI->cbSize != sizeof(SUBSCRIPTIONINFO)) { return FALSE; } else if (pSI->fUpdateFlags & ~SUBSINFO_ALLFLAGS) { return FALSE; } else if (pSI->pTrigger && ((TASK_TRIGGER*)(pSI->pTrigger))->cbTriggerSize && (subType == SUBSTYPE_URL || subType == SUBSTYPE_DESKTOPURL)) // || pSI->schedule != SUBSSCHED_AUTO))
{ return FALSE; } else if (pSI->fUpdateFlags & SUBSINFO_SCHEDULE) { if (pSI->schedule > SUBSCRIPTIONSCHEDULE_MAX) { return FALSE; } if (pSI->schedule == SUBSSCHED_CUSTOM && pSI->customGroupCookie == CLSID_NULL) { return FALSE; } }
return TRUE; }
////////////////////////////////////////////////////////////////////////////////
//
// *** RemoveURLMapping ***
//
// Description:
// Removes the cache and registry settings that wininet uses to map the
// given url to a local file.
//
////////////////////////////////////////////////////////////////////////////////
#define PRELOAD_REG_KEY \
TEXT("Software\\Microsoft\\Windows\\CurrentVersion\\Internet Settings\\Cache\\Preload")
void RemoveURLMapping(LPCWSTR pszURL) { BYTE cei[MY_MAX_CACHE_ENTRY_INFO]; DWORD cbcei = sizeof(cei); LPINTERNET_CACHE_ENTRY_INFOW pcei = (LPINTERNET_CACHE_ENTRY_INFOW)cei; //
// Look up the url in the cache
//
if (GetUrlCacheEntryInfoExW(pszURL, pcei, &cbcei, NULL, 0, NULL, 0)) { //
// see if it has a mapping because it is a preinstalled cache entry
//
if (pcei->CacheEntryType & INSTALLED_CACHE_ENTRY) { //
// Clear the flag
//
pcei->CacheEntryType &= ~INSTALLED_CACHE_ENTRY; SetUrlCacheEntryInfoW(pszURL, pcei, CACHE_ENTRY_ATTRIBUTE_FC);
//
// Now remove the mapping from the registry
//
HKEY hk; if (RegOpenKeyEx(HKEY_CURRENT_USER, PRELOAD_REG_KEY, 0, KEY_WRITE, &hk) == ERROR_SUCCESS) { RegDeleteValueW(hk, pszURL); RegCloseKey(hk); } } } }
//
// CSubscriptionMgr::CreateSubscription
// entry point for creating a subscription
// flags:
// CREATESUBS_FROMFAVORITES -- already exists in favorites, use alternate summary dialog
// that doesn't do AddToFavorites. Valid only for channel or url.
// CREATESUBS_INACTIVEPLATINUM -- when creating a channel subscription, show Activate Channel dialog
// valid only for channel subscriptions with CREATESUBS_FROMFAVORITES
// CREATESUBS_ADDTOFAVORITES -- display summary dialog before wizard
// default summary: for channel or url, use AddToFavorites from shdocvw
// for desktop item, just a confirmation dialog
// for other, no summary -- straight to wizard
// CREATESUBS_NOUI -- totally silent
// CREATESUBS_NOSAVE -- update subscription in memory buffer, not on disk (pInfo must be non-NULL)
//
STDMETHODIMP CSubscriptionMgr::CreateSubscription ( HWND hwnd, LPCWSTR pwszURL, LPCWSTR pwszFriendlyName, DWORD dwFlags, SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO *pInfo ) { HRESULT hr = E_INVALIDARG; BOOL bAlready;
if (IsFlagSet(dwFlags, CREATESUBS_NOUI) || !IsFlagSet (dwFlags, CREATESUBS_ADDTOFAVORITES)) { //no UI, so skip ATF dialog
hr = CreateSubscriptionNoSummary (hwnd, pwszURL, pwszFriendlyName, dwFlags, subsType, pInfo);
if (hr == S_OK) { //
// The user successfully subscribed to this URL so remove
// mappings used for preinstalled content as this URL is now
// "Activated"
//
RemoveURLMapping(pwszURL); } } else { switch (subsType) { case SUBSTYPE_URL: case SUBSTYPE_CHANNEL: hr = SHAddSubscribeFavorite (hwnd, pwszURL, pwszFriendlyName, dwFlags, subsType, pInfo); break;
case SUBSTYPE_DESKTOPCHANNEL: case SUBSTYPE_DESKTOPURL: hr = IsSubscribed (pwszURL, &bAlready); if (SUCCEEDED (hr) && bAlready) break; //don't display summary dialog since it has nothing useful for this case
hr = CreateDesktopSubscription (hwnd, pwszURL, pwszFriendlyName, dwFlags, subsType, pInfo); break;
default: //SUBSTYPE_EXTERNAL -- don't know what kind of summary to show
hr = CreateSubscriptionNoSummary (hwnd, pwszURL, pwszFriendlyName, dwFlags, subsType, pInfo); break; } }
return hr; }
//
// CSubscriptionMgr::CreateSubscriptionNoSummary
// modify a SUBSCRIPTIONINFO interactively, using the wizard
// persists info to Subscriptions folder, unless SUBSINFO_NOSAVE passed
//
STDMETHODIMP CSubscriptionMgr::CreateSubscriptionNoSummary ( HWND hwnd, LPCWSTR pwszURL, LPCWSTR pwszFriendlyName, DWORD dwFlags, SUBSCRIPTIONTYPE subType, SUBSCRIPTIONINFO *pInfo ) { HRESULT hr = S_OK; //
// Validate the parameters.
//
if (!IS_VALID_SUBSCRIPTIONTYPE(subType) || !pwszURL || !pwszFriendlyName || (!pInfo && (dwFlags & CREATESUBS_NOSAVE)) || (pInfo && !IsValidSubscriptionInfo(subType, pInfo))) { ASSERT(FALSE); return E_INVALIDARG; }
//
// Fail if already subscribed and we aren't in no save or no UI mode.
// Caller is responsible for UI.
//
BOOL fAlreadySubscribed; if ((FAILED(IsSubscribed(pwszURL, &fAlreadySubscribed)) || fAlreadySubscribed) && (!(dwFlags & (CREATESUBS_NOSAVE | CREATESUBS_NOUI)))) { return E_FAIL; }
//
// Fail if restrictions are in place.
// FEATURE: Currently cdfview is handling channel restrictions for
// but we should probably do it here.
// Should we have a flag parameter to override this?
//
if (SUBSTYPE_URL == subType) { DWORD dwMaxCount = SHRestricted2W(REST_MaxSubscriptionCount, NULL, 0); DWORD dwCount; if (SHRestricted2W(REST_NoAddingSubscriptions, pwszURL, 0) || ((dwMaxCount > 0) && SUCCEEDED(CountSubscriptions(subType, &dwCount)) && (dwCount >= dwMaxCount))) { if (!IsFlagSet(dwFlags, CREATESUBS_NOUI)) SGMessageBox(hwnd, IDS_RESTRICTED, MB_OK); return E_ACCESSDENIED; } } //
// Get the subscription defaults and merge in the caller's info
//
OOEBuf subProps; GetDefaultOOEBuf(&subProps, subType); //this is (intentionally) duplicated below... it needs to be after the ChangeSubscriptionValues()
//call, but we need to grab the url first to make sure it's subscribable.
MyOleStrToStrN(subProps.m_URL, INTERNET_MAX_URL_LENGTH, pwszURL);
// Does this mean we can't support plugin protocols?
if (/*(subType != SUBSTYPE_EXTERNAL) &&*/ !IsHTTPPrefixed(subProps.m_URL)) { return E_INVALIDARG; }
if (pInfo) { ChangeSubscriptionValues(&subProps, pInfo); if (fAlreadySubscribed) { ReadCookieFromInetDB(subProps.m_URL, &subProps.m_Cookie); subProps.m_dwPropSheetFlags |= PSF_IS_ALREADY_SUBSCRIBED; } }
// Disallow password caching if restriction is in place. This both
// skips the wizard page and prevents the caller's password from
// being saved.
if (SHRestricted2W(REST_NoSubscriptionPasswords, NULL, 0)) { subProps.bNeedPassword = FALSE; subProps.username[0] = 0; subProps.password[0] = 0; subProps.dwFlags &= ~(PROP_WEBCRAWL_UNAME | PROP_WEBCRAWL_PSWD); }
//the passed-in name and url override whatever's in the info buffer
MyOleStrToStrN(subProps.m_URL, INTERNET_MAX_URL_LENGTH, pwszURL); MyOleStrToStrN(subProps.m_Name, MAX_NAME_QUICKLINK, pwszFriendlyName);
//
// If we're in UI mode, initialize the wizard
//
if (!IsFlagSet(dwFlags, CREATESUBS_NOUI)) { hr = CreateWizard(hwnd, subType, &subProps);
} // !NOUI
//
// If we're not in NOSAVE mode, then create/save the subscription
//
if (SUCCEEDED(hr)) { if (!IsFlagSet(dwFlags, CREATESUBS_NOSAVE)) { //hack to let AddToFavorites dialog display the screen-saver-activate dialog -- it
//needs to pass NOUI, which disables all UI, but if you also pass FROMFAVORITES and not
//ADDTOFAVORITES then we still let this dialog slip through. (Shouldn't affect anyone
//else because FROMFAVORITES is always used with ADDTOFAVORITES.)
if (!IsFlagSet(dwFlags, CREATESUBS_NOUI) || (IsFlagSet(dwFlags, CREATESUBS_FROMFAVORITES) && !IsFlagSet (dwFlags, CREATESUBS_ADDTOFAVORITES))) { // See if the user wants to be asked about enabling the screen saver.
DWORD dwValue = BST_UNCHECKED; ReadRegValue( HKEY_CURRENT_USER, WEBCHECK_REGKEY, g_szDontAskScreenSaver, &dwValue, SIZEOF(dwValue));
if ( (subProps.fChannelFlags & CHANNEL_AGENT_PRECACHE_SCRNSAVER) && (dwValue == BST_UNCHECKED) && !IsADScreenSaverActive() ) { DialogBoxParam( MLGetHinst(), MAKEINTRESOURCE(IDD_SUBSCRIPTION_ENABLECHANNELSAVER), hwnd, EnableScreenSaverDlgProc, 0L); } }
//
// Create a new pidl with the user specified properties.
//
if (_pidl) { COfflineFolderEnum::FreePidl(_pidl); _pidl = NULL; SAFERELEASE(m_pUIHelper); } hr = CreateSubscriptionFromOOEBuf(&subProps, &_pidl); if (SUCCEEDED(hr)) { ASSERT(_pidl); //
// Send a notification that a subscription has changed.
//
_GenerateEvent(SHCNE_CREATE, (LPITEMIDLIST)_pidl, NULL); } } //!NOSAVE
else if (S_OK == hr) { //in NOSAVE mode, so don't actually create subscription -- save it back
//to passed-in buffer
ASSERT (pInfo); pInfo->fUpdateFlags = SUBSINFO_ALLFLAGS; //fill in all possible fields
UpdateSubsInfoFromOOE (pInfo, &subProps); } } return hr; }
STDMETHODIMP CSubscriptionMgr::CreateDesktopSubscription (HWND hwnd, LPCWSTR pwszURL, LPCWSTR pwszFriendlyName, DWORD dwFlags, SUBSCRIPTIONTYPE subsType, SUBSCRIPTIONINFO *pInfo) { HRESULT hr; SUBSCRIPTIONINFO siTemp = { sizeof(SUBSCRIPTIONINFO), 0 }; if (!pInfo) pInfo = &siTemp; //make sure we have a valid buffer if caller doesn't give us one
//make sure adminrestrictions allow this
if (SHRestricted2W(REST_NoAddingChannels, pwszURL, 0)) return E_FAIL;
SUBSCRIBE_ADI_INFO parms = { this, pwszFriendlyName, pwszURL, pInfo, subsType, dwFlags };
//make sure this url is subscribable; if not, show error dialog
{ TCHAR sz[MAX_URL]; MyOleStrToStrN (sz, ARRAYSIZE(sz), pwszURL);
if (!IsHTTPPrefixed (sz)) { SGMessageBox(hwnd, IDS_HTTPONLY, MB_ICONINFORMATION | MB_OK); return E_INVALIDARG; } }
INT_PTR iDlgResult = DialogBoxParam (MLGetHinst(), MAKEINTRESOURCE(IDD_DESKTOP_SUBSCRIPTION_SUMMARY), hwnd, SummarizeDesktopSubscriptionDlgProc, (LPARAM)&parms);
switch (iDlgResult) { case -1: hr = E_FAIL; break; case IDCANCEL: hr = S_FALSE; break; default: hr = CreateSubscriptionNoSummary (hwnd, pwszURL, pwszFriendlyName, CREATESUBS_NOUI | dwFlags, subsType, pInfo); break; }
return hr; }
STDMETHODIMP CSubscriptionMgr::GetDefaultInfo( SUBSCRIPTIONTYPE subType, SUBSCRIPTIONINFO *pInfo ) { //
// Validate the parameters.
//
if (!IS_VALID_SUBSCRIPTIONTYPE(subType) || !pInfo || (pInfo->cbSize != sizeof(SUBSCRIPTIONINFO))) { ASSERT(FALSE); return E_INVALIDARG; }
memset((void *)pInfo, 0, sizeof(SUBSCRIPTIONINFO)); pInfo->cbSize = sizeof(SUBSCRIPTIONINFO);
// Fill in default structure. Note that lines are commented out
// below to indicate the field is initialized to 0 without wasting
// code (memset above already cleared structure out.)
pInfo->fUpdateFlags = SUBSINFO_RECURSE | SUBSINFO_MAILNOT | SUBSINFO_WEBCRAWL /*| SUBSINFO_SCHEDULE */ | SUBSINFO_CHANGESONLY | SUBSINFO_CHANNELFLAGS; pInfo->dwRecurseLevels = DEFAULTLEVEL; pInfo->schedule = SUBSSCHED_AUTO; switch (subType) { case SUBSTYPE_URL: // pInfo->bChangesOnly = FALSE;
// pInfo->bMailNotification = FALSE;
// pInfo->bPasswordNeeded = FALSE;
pInfo->fWebcrawlerFlags = DEFAULTFLAGS; break;
case SUBSTYPE_CHANNEL: // pInfo->bChangesOnly = FALSE;
// pInfo->bMailNotification = FALSE;
pInfo->fChannelFlags = CHANNEL_AGENT_PRECACHE_ALL | CHANNEL_AGENT_DYNAMIC_SCHEDULE; break;
case SUBSTYPE_DESKTOPCHANNEL: // pInfo->bChangesOnly = FALSE;
// pInfo->bMailNotification = FALSE;
pInfo->fChannelFlags = CHANNEL_AGENT_PRECACHE_ALL | CHANNEL_AGENT_DYNAMIC_SCHEDULE; break; case SUBSTYPE_DESKTOPURL: // pInfo->bChangesOnly = FALSE;
// pInfo->bMailNotification = FALSE;
pInfo->fWebcrawlerFlags = DEFAULTFLAGS; break; default: return E_NOTIMPL; } return S_OK; }
STDMETHODIMP CSubscriptionMgr::GetSubscriptionInfo( LPCWSTR pwszURL, SUBSCRIPTIONINFO *pInfo ) { HRESULT hr;
//
// Validate the parameters.
//
if (!pInfo || !pwszURL || (pInfo->cbSize != sizeof(SUBSCRIPTIONINFO))) { ASSERT(FALSE); return E_INVALIDARG; }
BOOL bSubscribe; hr = IsSubscribed(pwszURL, &bSubscribe);
RETURN_ON_FAILURE(hr); if (!bSubscribe) { return E_FAIL; }
// We cannot rely on the caller passing us a clean SUBSCRIPTIONINFO
// structure. We need to clean it ourselves.
DWORD dwFlags = pInfo->fUpdateFlags; ZeroMemory(pInfo, sizeof(SUBSCRIPTIONINFO)); pInfo->cbSize = sizeof(SUBSCRIPTIONINFO); pInfo->fUpdateFlags = dwFlags;
OOEBuf ooeb; // Alas, we need the code in UpdateSubsInfoFromOOE
CopyToOOEBuf (&(_pidl->ooe), &ooeb); //to work once for a buf and once for an entry, and it's
UpdateSubsInfoFromOOE (pInfo, &ooeb); //easier to convert entry->buf so we do that here.
return S_OK; }
void UpdateSubsInfoFromOOE (SUBSCRIPTIONINFO* pInfo, POOEBuf pooe) { DWORD dwFlags = pInfo->fUpdateFlags & SUBSINFO_ALLFLAGS; SUBSCRIPTIONTYPE subType = GetItemCategory(pooe);
if (dwFlags & SUBSINFO_USER) { SAFEFREEBSTR (pInfo->bstrUserName); CreateBSTRFromTSTR(&(pInfo->bstrUserName), pooe->username); } if (dwFlags & SUBSINFO_PASSWORD) { SAFEFREEBSTR (pInfo->bstrPassword); CreateBSTRFromTSTR(&(pInfo->bstrPassword), pooe->password); } if (dwFlags & SUBSINFO_FRIENDLYNAME) { SAFEFREEBSTR (pInfo->bstrFriendlyName); CreateBSTRFromTSTR(&(pInfo->bstrFriendlyName), pooe->m_Name); } pInfo->fUpdateFlags = dwFlags; if (dwFlags & SUBSINFO_SCHEDULE) { pInfo->schedule = GetGroup(pooe); if (pInfo->schedule == SUBSSCHED_CUSTOM) { if (pooe->groupCookie != GUID_NULL) { pInfo->customGroupCookie = pooe->groupCookie; } else { GetItemSchedule(&pooe->m_Cookie, &pInfo->customGroupCookie); if (pInfo->customGroupCookie == GUID_NULL) { pInfo->schedule = SUBSSCHED_MANUAL; } } } } if (PTASK_TRIGGER pInfoTrigger = (PTASK_TRIGGER)pInfo->pTrigger) { if (pInfoTrigger->cbTriggerSize == pooe->m_Trigger.cbTriggerSize) *(pInfoTrigger) = pooe->m_Trigger; else pInfoTrigger->cbTriggerSize = 0; } //otherwise, it's already null and we can't do anything about it... luckily, we'll never
//have a trigger that we need to write back to a SUBSCRIPTIONINFO that didn't already have
//one.
if (dwFlags & SUBSINFO_RECURSE) pInfo->dwRecurseLevels = pooe->m_RecurseLevels; if (dwFlags & SUBSINFO_WEBCRAWL) pInfo->fWebcrawlerFlags = pooe->m_RecurseFlags; if (dwFlags & SUBSINFO_MAILNOT) pInfo->bMailNotification = pooe->bMail; if (dwFlags & SUBSINFO_GLEAM) pInfo->bGleam = pooe->bGleam; if (dwFlags & SUBSINFO_CHANGESONLY) pInfo->bChangesOnly = pooe->bChangesOnly; if (dwFlags & SUBSINFO_NEEDPASSWORD) pInfo->bNeedPassword = pooe->bNeedPassword; if (dwFlags & SUBSINFO_CHANNELFLAGS) { if ((subType==SUBSTYPE_CHANNEL)||(subType==SUBSTYPE_DESKTOPCHANNEL)) { pInfo->fChannelFlags = pooe->fChannelFlags; } else { pInfo->fChannelFlags = 0; pInfo->fUpdateFlags &= (~SUBSINFO_CHANNELFLAGS); } } if (dwFlags & SUBSINFO_MAXSIZEKB) pInfo->dwMaxSizeKB = pooe->m_SizeLimit;
if (dwFlags & SUBSINFO_TYPE) { pInfo->subType = GetItemCategory(pooe); ASSERT(IS_VALID_SUBSCRIPTIONTYPE(pInfo->subType)); }
if (dwFlags & SUBSINFO_TASKFLAGS) { pInfo->fTaskFlags = pooe->grfTaskTrigger; }
}
STDMETHODIMP CSubscriptionMgr::UpdateSubscription(LPCWSTR pwszURL) { ASSERT(pwszURL); BOOL bSubscribe = FALSE; HRESULT hr = IsSubscribed(pwszURL, &bSubscribe); CLSID clsId;
RETURN_ON_FAILURE(hr); if (!bSubscribe) { return E_INVALIDARG; }
//
// Fail if restrictions are in place.
// FEATURE: Should we have a flag parameter to override this?
//
if (SHRestricted2W(REST_NoManualUpdates, NULL, 0)) { SGMessageBox(NULL, IDS_RESTRICTED, MB_OK); return E_ACCESSDENIED; }
clsId = _pidl->ooe.m_Cookie; hr = SendUpdateRequests(NULL, &clsId, 1); _pidl->ooe.m_Cookie = clsId;
return hr; }
STDMETHODIMP CSubscriptionMgr::UpdateAll() { //
// Fail if restrictions are in place.
// FEATURE: Should we have a flag parameter to override this?
//
if (SHRestricted2W(REST_NoManualUpdates, NULL, 0)) { SGMessageBox(NULL, IDS_RESTRICTED, MB_OK); return E_ACCESSDENIED; }
return SendUpdateRequests(NULL, NULL, 0); }
HRESULT MergeOOEBuf(POOEBuf p1, POOEBuf p2, DWORD fMask) { ASSERT(p1 && p2); DWORD dwMask = p2->dwFlags & fMask;
if (dwMask == 0) return S_OK;
if (p1->clsidDest != p2->clsidDest) return E_INVALIDARG;
if (dwMask & PROP_WEBCRAWL_COOKIE) { // We shouldn't merge cookies.
}
if (dwMask & PROP_WEBCRAWL_SIZE) { p1->m_SizeLimit = p2->m_SizeLimit; } if (dwMask & PROP_WEBCRAWL_FLAGS) { p1->m_RecurseFlags = p2->m_RecurseFlags; } if (dwMask & PROP_WEBCRAWL_LEVEL) { p1->m_RecurseLevels = p2->m_RecurseLevels; } if (dwMask & PROP_WEBCRAWL_URL) { StrCpyN(p1->m_URL, p2->m_URL, MAX_URL); } if (dwMask & PROP_WEBCRAWL_NAME) { StrCpyN(p1->m_Name, p2->m_Name, MAX_NAME); }
if (dwMask & PROP_WEBCRAWL_PSWD) { StrCpyN(p1->password, p2->password, MAX_PASSWORD); } if (dwMask & PROP_WEBCRAWL_UNAME) { StrCpyN(p1->username, p2->username, MAX_USERNAME); } if (dwMask & PROP_WEBCRAWL_DESKTOP) { p1->bDesktop = p2->bDesktop; } if (dwMask & PROP_WEBCRAWL_CHANNEL) { p1->bChannel = p2->bChannel; } if (dwMask & PROP_WEBCRAWL_EMAILNOTF) { p1->bMail = p2->bMail; } if (dwMask & PROP_WEBCRAWL_RESCH) { p1->grfTaskTrigger = p2->grfTaskTrigger; p1->groupCookie = p2->groupCookie; p1->fChannelFlags |= (p2->fChannelFlags & CHANNEL_AGENT_DYNAMIC_SCHEDULE); } if (dwMask & PROP_WEBCRAWL_LAST) { p1->m_LastUpdated = p2->m_LastUpdated; } if (dwMask & PROP_WEBCRAWL_STATUS) { p1->status = p2->status; } if (dwMask & PROP_WEBCRAWL_PRIORITY) { p1->m_Priority = p2->m_Priority; } if (dwMask & PROP_WEBCRAWL_GLEAM) { p1->bGleam = p2->bGleam; } if (dwMask & PROP_WEBCRAWL_CHANGESONLY) { p1->bChangesOnly = p2->bChangesOnly; } if (dwMask & PROP_WEBCRAWL_CHANNELFLAGS) { p1->fChannelFlags = p2->fChannelFlags; }
p1->dwFlags |= (p2->dwFlags & fMask & (~PROP_WEBCRAWL_COOKIE));
return S_OK; }
INT_PTR CALLBACK SummarizeDesktopSubscriptionDlgProc(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { SUBSCRIBE_ADI_INFO* pInfo = (SUBSCRIBE_ADI_INFO*)GetProp(hDlg,SUBSCRIBEADIPROP);
switch (uMsg) { case WM_INITDIALOG: pInfo = (SUBSCRIBE_ADI_INFO*)lParam; ASSERT (pInfo); SetProp (hDlg, SUBSCRIBEADIPROP, (HANDLE)pInfo); { //block to declare vars to update captions
TCHAR sz[MAX_URL];
if (pInfo->subsType == SUBSTYPE_DESKTOPCHANNEL) { if(MLLoadString( (pInfo->pSubsInfo->bNeedPassword ? IDS_DESKTOPCHANNEL_SUMMARY_TEXT : IDS_DESKTOPCHANNEL_SUMMARY_NOPW), sz, ARRAYSIZE(sz))) { SetDlgItemText(hDlg, IDC_DESKTOP_SUMMARY_TEXT, sz); } }
MyOleStrToStrN (sz, ARRAYSIZE(sz), pInfo->pwszName); SetListViewToString(GetDlgItem(hDlg, IDC_SUBSCRIBE_ADI_NAME), sz); MyOleStrToStrN (sz, ARRAYSIZE(sz), pInfo->pwszUrl); SetListViewToString (GetDlgItem (hDlg, IDC_SUBSCRIBE_ADI_URL), sz); } break;
case WM_COMMAND: ASSERT (pInfo); switch (GET_WM_COMMAND_ID(wParam, lParam)) { case IDCANCEL: EndDialog(hDlg, IDCANCEL); break;
case IDOK: //subscription happens in calling function when we return IDOK
EndDialog(hDlg, IDOK); break;
case IDC_SUBSCRIBE_CUSTOMIZE: //run through wizard in NOSAVE mode
if (pInfo->pMgr && S_OK == pInfo->pMgr->CreateSubscriptionNoSummary (hDlg, pInfo->pwszUrl, pInfo->pwszName, pInfo->dwFlags | CREATESUBS_NOSAVE, pInfo->subsType, pInfo->pSubsInfo)) { SendMessage (hDlg, WM_NEXTDLGCTL, (WPARAM)GetDlgItem(hDlg, IDOK), TRUE); } break; } break;
case WM_NOTIFY: if (LOWORD(wParam) == IDC_SUBSCRIBE_ADI_URL) { NM_LISTVIEW * pnmlv = (NM_LISTVIEW *)lParam; if (pnmlv->hdr.code == LVN_GETINFOTIP) { TCHAR szURL[MAX_URL]; LV_ITEM lvi = {0}; lvi.mask = LVIF_TEXT; lvi.pszText = szURL; lvi.cchTextMax = ARRAYSIZE(szURL); if (!ListView_GetItem (GetDlgItem (hDlg, IDC_SUBSCRIBE_ADI_URL), &lvi)) return FALSE;
NMLVGETINFOTIP * pTip = (NMLVGETINFOTIP *)pnmlv; ASSERT(pTip); StrCpyN(pTip->pszText, szURL, pTip->cchTextMax); return TRUE; } } break;
case WM_DESTROY: RemoveProp (hDlg, SUBSCRIBEADIPROP); break; }
return FALSE; }
|