|
|
#include "private.h"
#include "chanmgr.h"
#include "chanmgrp.h"
#include "shguidp.h"
#include "resource.h"
#define DECL_CRTFREE
#include <crtfree.h>
#include <mluisupp.h>
#define TF_DUMPTRIGGER 0x80000000
#define PtrDifference(x,y) ((LPBYTE)(x)-(LPBYTE)(y))
// Invoke Command verb strings
const CHAR c_szOpen[] = "open"; const CHAR c_szDelete[] = "delete"; const CHAR c_szProperties[] = "properties"; const CHAR c_szCopy[] = "copy"; const CHAR c_szRename[] = "rename"; const CHAR c_szPaste[] = "paste";
static TCHAR szNone[40] = {0}; static TCHAR szUnknown[40] = {0};
// For each notification handler CLSID in the registry, send a single CommandId and Cookie to each handler.
void FireSubscriptionEvent(int nCmdID, const SUBSCRIPTIONCOOKIE UNALIGNED *pCookie_ua) { HKEY hkey; SUBSCRIPTIONCOOKIE cookie_buf; SUBSCRIPTIONCOOKIE *pCookie;
ASSERT( pCookie_ua );
if ( ! pCookie_ua ) { TraceMsg(TF_ERROR, "FireSubscriptionEvent() - pCookie_ua is NULL!"); return; }
//
// Make an aligned copy of pCookie_ua and set a pointer to it.
//
cookie_buf = *pCookie_ua; pCookie = &cookie_buf;
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, WEBCHECK_REGKEY_NOTF, 0, KEY_READ, &hkey) == ERROR_SUCCESS) { LPOLESTR pszCookie;
if (SUCCEEDED(StringFromCLSID(*pCookie, &pszCookie))) { VARIANT varCookie;
varCookie.vt = VT_BSTR; varCookie.bstrVal = SysAllocString(pszCookie);
if (varCookie.bstrVal) { for (int i = 0; ; i++) { TCHAR szClsid[GUIDSTR_MAX]; DWORD cchClsid = ARRAYSIZE(szClsid); DWORD dwType; DWORD dwData; DWORD cbData = sizeof(dwData);
int result = RegEnumValue(hkey, i, szClsid, &cchClsid, NULL, &dwType, (LPBYTE)&dwData, &cbData);
if (ERROR_NO_MORE_ITEMS == result) { break; }
if ((ERROR_SUCCESS == result) && (dwData & nCmdID)) { WCHAR wszClsid[GUIDSTR_MAX]; CLSID clsid;
SHTCharToUnicode(szClsid, wszClsid, ARRAYSIZE(wszClsid));
HRESULT hr = CLSIDFromString(wszClsid, &clsid);
if (SUCCEEDED(hr)) { IOleCommandTarget *pCmdTarget;
hr = CoCreateInstance(*(&clsid), NULL, CLSCTX_ALL, IID_IOleCommandTarget, (void **)&pCmdTarget); if (SUCCEEDED(hr)) { pCmdTarget->Exec(&CLSID_SubscriptionMgr, nCmdID, 0, &varCookie, NULL); pCmdTarget->Release(); } } } }
VariantClear(&varCookie); }
CoTaskMemFree(pszCookie); }
RegCloseKey( hkey ); } }
HRESULT IExtractIcon_GetIconLocationThunk(IExtractIconW *peiw, UINT uFlags, LPSTR szIconFile, UINT cchMax, int * piIndex, UINT * pwFlags) { HRESULT hr; WCHAR *pwszIconFile = new WCHAR[cchMax];
if (NULL != pwszIconFile) { hr = peiw->GetIconLocation(uFlags, pwszIconFile, cchMax, piIndex, pwFlags);
if (SUCCEEDED(hr)) { WideCharToMultiByte(CP_ACP, 0, pwszIconFile, -1, szIconFile, cchMax, NULL, NULL); }
delete [] pwszIconFile; } else { hr = E_OUTOFMEMORY; }
return hr; }
HRESULT IExtractIcon_ExtractThunk(IExtractIconW *peiw, LPCSTR pszFile, UINT nIconIndex, HICON * phiconLarge, HICON * phiconSmall, UINT nIconSize) { HRESULT hr; int len = lstrlenA(pszFile) + 1; WCHAR *pwszFile = new WCHAR[len];
if (NULL != pwszFile) { MultiByteToWideChar(CP_ACP, 0, pszFile, len, pwszFile, len);
hr = peiw->Extract(pwszFile, nIconIndex, phiconLarge, phiconSmall, nIconSize);
delete [] pwszFile; } else { hr = E_OUTOFMEMORY; }
return hr; }
DWORD Random(DWORD nMax) { static DWORD dwSeed = GetTickCount();
if (nMax) { return dwSeed = (dwSeed * 214013L + 2531011L) % nMax; } else { return 0; } }
void CreateCookie(GUID UNALIGNED *pCookie_ua) { static DWORD dwCount = 0;
union CUCookie { GUID guidCookie; struct XCookie { FILETIME ft; DWORD dwCount; DWORD dwRand; } x; };
CUCookie uc; GetSystemTimeAsFileTime(&uc.x.ft); uc.x.dwCount = dwCount++; uc.x.dwRand = Random(0xffffffff);
*pCookie_ua = uc.guidCookie; }
void VariantTimeToFileTime(double dt, FILETIME& ft) { SYSTEMTIME st;
VariantTimeToSystemTime(dt, &st); SystemTimeToFileTime(&st, &ft); }
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Cache helper functions
//
// Caller should MemFree *lpCacheConfigInfo when done. Should pass *lpCacheConfigInfo
// into SetCacheSize
HRESULT GetCacheInfo( LPINTERNET_CACHE_CONFIG_INFOA *lplpCacheConfigInfo, DWORD *pdwSizeInKB, DWORD *pdwPercent) { HRESULT hr = S_OK; LPINTERNET_CACHE_CONFIG_INFOA lpCCI = NULL; DWORD dwSize;
dwSize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
lpCCI = (LPINTERNET_CACHE_CONFIG_INFOA)MemAlloc(LPTR, dwSize);
if (!lpCCI) { hr = E_OUTOFMEMORY; goto cleanup; }
lpCCI->dwStructSize = sizeof(INTERNET_CACHE_CONFIG_INFOA);
if (!GetUrlCacheConfigInfoA(lpCCI, &dwSize, CACHE_CONFIG_CONTENT_PATHS_FC)) { hr = E_FAIL; // HRESULT_FROM_WIN32(GetLastError());
goto cleanup; }
// there should be at least one cache path structure
if (dwSize < sizeof(INTERNET_CACHE_CONFIG_INFOA) || lpCCI->dwNumCachePaths != 1) { // something is messed up
hr = E_FAIL; goto cleanup; }
*lplpCacheConfigInfo = lpCCI; *pdwSizeInKB = lpCCI->dwQuota; *pdwPercent = 10; // good faith estimate
ASSERT(*pdwSizeInKB); // Better not be 0...
cleanup:
if (FAILED(hr)) { SAFELOCALFREE(lpCCI); }
return hr; }
HRESULT SetCacheSize( LPINTERNET_CACHE_CONFIG_INFOA lpCacheConfigInfo, DWORD dwSizeInKB) { // lpCacheConfigInfo->dwNumCachePaths = 1;
// lpCacheConfigInfo->CachePaths[0].dwCacheSize = dwSizeInKB;
lpCacheConfigInfo->dwContainer = 0; // CONTENT;
lpCacheConfigInfo->dwQuota = dwSizeInKB;
if (!SetUrlCacheConfigInfoA(lpCacheConfigInfo, CACHE_CONFIG_QUOTA_FC)) { return E_FAIL; // HRESULT_FROM_WIN32(GetLastError());
}
return S_OK; }
//////////////////////////////////////////////////////////////////////////
//////////////////////////////////////////////////////////////////////////
//
// Registry helper functions
//
BOOL ReadRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue, void *pData, DWORD dwBytes) { return ERROR_SUCCESS == SHRegGetValue(hkeyRoot, pszKey, pszValue, SRRF_RT_ANY | SRRF_NOEXPAND, NULL, pData, &dwBytes); }
BOOL WriteRegValue(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue, void *pData, DWORD dwBytes, DWORD dwType) { HKEY hkey; long lResult; DWORD dwStatus;
lResult = RegCreateKeyEx(hkeyRoot, pszKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, NULL, &hkey, &dwStatus); if (lResult != ERROR_SUCCESS) { return FALSE; }
lResult = RegSetValueEx(hkey, pszValue, 0, dwType, (BYTE *)pData, dwBytes); RegCloseKey(hkey);
return (lResult == ERROR_SUCCESS) ? TRUE : FALSE; }
DWORD ReadRegDWORD(HKEY hkeyRoot, const TCHAR *pszKey, const TCHAR *pszValue) { DWORD dwData; if (ReadRegValue(hkeyRoot, pszKey, pszValue, &dwData, sizeof(dwData))) return dwData; else return 0; }
HRESULT CreateShellFolderPath(LPCTSTR pszPath, LPCTSTR pszGUID, BOOL bUICLSID) { if (!PathFileExists(pszPath)) CreateDirectory(pszPath, NULL);
// Mark the folder as a system directory
if (SetFileAttributes(pszPath, FILE_ATTRIBUTE_READONLY)) { TCHAR szDesktopIni[MAX_PATH]; // Write in the desktop.ini the cache folder class ID
PathCombine(szDesktopIni, pszPath, TEXT("desktop.ini"));
// If the desktop.ini already exists, make sure it is writable
if (PathFileExists(szDesktopIni)) SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_NORMAL);
// (First, flush the cache to make sure the desktop.ini
// file is really created.)
WritePrivateProfileString(NULL, NULL, NULL, szDesktopIni); WritePrivateProfileString(TEXT(".ShellClassInfo"), bUICLSID ? TEXT("UICLSID") : TEXT("CLSID"), pszGUID, szDesktopIni); WritePrivateProfileString(NULL, NULL, NULL, szDesktopIni);
// Hide the desktop.ini since the shell does not selectively
// hide it.
SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_HIDDEN);
return NOERROR; } else { DebugMsg(DM_TRACE, TEXT("Cannot make %s a system folder"), pszPath); return E_FAIL; } }
void CleanupShellFolder(LPCTSTR pszPath) { if (PathFileExists(pszPath)) { TCHAR szDesktopIni[MAX_PATH];
// make the history a normal folder
SetFileAttributes(pszPath, FILE_ATTRIBUTE_NORMAL); PathCombine(szDesktopIni, pszPath, TEXT("desktop.ini"));
// If the desktop.ini already exists, make sure it is writable
if (PathFileExists(szDesktopIni)) { SetFileAttributes(szDesktopIni, FILE_ATTRIBUTE_NORMAL); DeleteFile(szDesktopIni); }
// remove the history directory
RemoveDirectory(pszPath); } }
BOOL GetSubscriptionFolderPath(LPTSTR pszPath, DWORD cchPath) { DWORD dwDummy; HKEY hk;
if (ERROR_SUCCESS == RegCreateKeyEx(HKEY_LOCAL_MACHINE, REGSTR_PATH_SUBSCRIPTION, 0, TEXT(""), REG_OPTION_NON_VOLATILE, KEY_READ|KEY_WRITE, NULL, &hk, &dwDummy)) { DWORD cbData = cchPath * sizeof(TCHAR); if (ERROR_SUCCESS != SHRegGetValue(hk, NULL, REGSTR_VAL_DIRECTORY, SRRF_RT_REG_SZ | SRRF_RT_REG_EXPAND_SZ | SRRF_NOEXPAND, NULL, pszPath, &cbData)) { TCHAR szWindows[MAX_PATH]; GetWindowsDirectory(szWindows, ARRAYSIZE(szWindows)); PathCombine(pszPath, szWindows, TEXT("Offline Web Pages")); } RegCloseKey(hk);
return TRUE; } return FALSE; }
HRESULT GetChannelPath(LPCTSTR pszURL, LPTSTR pszPath, int cch, IChannelMgrPriv** ppIChannelMgrPriv) { ASSERT(pszURL); ASSERT(pszPath || 0 == cch); ASSERT(ppIChannelMgrPriv);
HRESULT hr; BOOL bCoinit = FALSE;
hr = CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER, IID_IChannelMgrPriv, (void**)ppIChannelMgrPriv);
if ((hr == CO_E_NOTINITIALIZED || hr == REGDB_E_IIDNOTREG) && SUCCEEDED(CoInitialize(NULL))) { bCoinit = TRUE; hr = CoCreateInstance(CLSID_ChannelMgr, NULL, CLSCTX_INPROC_SERVER, IID_IChannelMgrPriv, (void**)ppIChannelMgrPriv); }
if (SUCCEEDED(hr)) { ASSERT(*ppIChannelMgrPriv);
IChannelMgr* pIChannelMgr;
hr = (*ppIChannelMgrPriv)->QueryInterface(IID_IChannelMgr, (void**)&pIChannelMgr);
if (SUCCEEDED(hr)) { ASSERT(pIChannelMgr);
WCHAR wszURL[INTERNET_MAX_URL_LENGTH]; MyStrToOleStrN(wszURL, ARRAYSIZE(wszURL), pszURL);
IEnumChannels* pIEnumChannels;
hr = pIChannelMgr->EnumChannels(CHANENUM_ALLFOLDERS | CHANENUM_PATH, wszURL, &pIEnumChannels);
if (SUCCEEDED(hr)) { ASSERT(pIEnumChannels);
CHANNELENUMINFO ci;
if (S_OK == pIEnumChannels->Next(1, &ci, NULL)) { MyOleStrToStrN(pszPath, cch, ci.pszPath);
CoTaskMemFree(ci.pszPath); } else { hr = E_FAIL; }
pIEnumChannels->Release(); }
pIChannelMgr->Release(); }
}
if (bCoinit) CoUninitialize();
ASSERT((SUCCEEDED(hr) && *ppIChannelMgrPriv) || FAILED(hr));
return hr; }
// Caller is responsible for calling ILFree on *ppidl.
HRESULT ConvertPathToPidl(LPCTSTR path, LPITEMIDLIST * ppidl) { WCHAR wszPath[MAX_PATH]; IShellFolder * pDesktopFolder; HRESULT hr;
ASSERT(path && ppidl); * ppidl = NULL;
MyStrToOleStrN(wszPath, MAX_PATH, path); hr = SHGetDesktopFolder(&pDesktopFolder); if (hr != NOERROR) return hr;
ULONG uChEaten;
hr = pDesktopFolder->ParseDisplayName(NULL, NULL, wszPath, &uChEaten, ppidl, NULL); SAFERELEASE(pDesktopFolder);
return hr; }
LPITEMIDLIST GetSubscriptionFolderPidl(void) { TCHAR szPath[MAX_PATH]; static LPITEMIDLIST pidlFolder = NULL; // We leak here.
if (!pidlFolder) { if (!(GetSubscriptionFolderPath(szPath, ARRAYSIZE(szPath)))) return NULL; if (FAILED(ConvertPathToPidl(szPath, &pidlFolder))) return NULL; ASSERT(pidlFolder); } return (LPITEMIDLIST)pidlFolder; }
STDAPI OfflineFolderRegisterServer(void) { TCHAR szOldSubscriptionPath[MAX_PATH];
GetWindowsDirectory(szOldSubscriptionPath, ARRAYSIZE(szOldSubscriptionPath)); PathCombine(szOldSubscriptionPath, szOldSubscriptionPath, TEXT("Subscriptions")); CleanupShellFolder(szOldSubscriptionPath);
TCHAR szPath[MAX_PATH];
if (!(GetSubscriptionFolderPath(szPath, ARRAYSIZE(szPath)))) goto CleanUp;
// we pass FALSE because history folder uses CLSID
if (FAILED(CreateShellFolderPath(szPath, TEXT("{F5175861-2688-11d0-9C5E-00AA00A45957}"), FALSE))) goto CleanUp;
return NOERROR;
CleanUp: // cleanup stuff if any of our reg stuff fails
return E_FAIL; }
STDAPI OfflineFolderUnregisterServer(void) { TCHAR szPath[MAX_PATH];
if (!(GetSubscriptionFolderPath(szPath, ARRAYSIZE(szPath)))) goto CleanUp;
// we pass FALSE because history folder uses CLSID
CleanupShellFolder(szPath);
return NOERROR;
CleanUp: // cleanup stuff if any of our reg stuff fails
return E_FAIL; }
HMENU LoadPopupMenu(UINT id, UINT uSubOffset) { HMENU hmParent, hmPopup;
hmParent = LoadMenu(MLGetHinst(), MAKEINTRESOURCE(id)); if (!hmParent) return NULL;
hmPopup = GetSubMenu(hmParent, uSubOffset); RemoveMenu(hmParent, uSubOffset, MF_BYPOSITION); DestroyMenu(hmParent);
return hmPopup; }
UINT MergePopupMenu(HMENU *phMenu, UINT idResource, UINT uSubOffset, UINT indexMenu, UINT idCmdFirst, UINT idCmdLast) { HMENU hmMerge;
if (*phMenu == NULL) { *phMenu = CreatePopupMenu(); if (*phMenu == NULL) return 0;
indexMenu = 0; // at the bottom
}
hmMerge = LoadPopupMenu(idResource, uSubOffset); if (!hmMerge) return 0;
idCmdLast = Shell_MergeMenus(*phMenu, hmMerge, indexMenu, idCmdFirst, idCmdLast, MM_ADDSEPARATOR);
DestroyMenu(hmMerge); return idCmdLast; }
HMENU GetMenuFromID(HMENU hmenu, UINT idm) { MENUITEMINFO mii = { sizeof(mii), MIIM_SUBMENU, 0, 0, 0, NULL, NULL, NULL, 0, NULL, 0 }; GetMenuItemInfo(hmenu, idm, FALSE, &mii); return mii.hSubMenu; }
UINT MergeMenuHierarchy(HMENU hmenuDst, HMENU hmenuSrc, UINT idcMin, UINT idcMax, BOOL bTop) { UINT idcMaxUsed = idcMin; int imi = GetMenuItemCount(hmenuSrc);
while (--imi >= 0) { MENUITEMINFO mii = { sizeof(MENUITEMINFO), MIIM_ID | MIIM_SUBMENU, 0,/* fType */ 0,/* fState */ 0,/*wId*/ NULL, NULL, NULL, 0, NULL, 0 };
if (GetMenuItemInfo(hmenuSrc, imi, TRUE, &mii)) { UINT idcT = Shell_MergeMenus( GetMenuFromID(hmenuDst, mii.wID), mii.hSubMenu, (bTop)?0:1024, idcMin, idcMax, MM_ADDSEPARATOR | MM_SUBMENUSHAVEIDS); idcMaxUsed = max(idcMaxUsed, idcT); } } return idcMaxUsed; }
///////////////////////////////////////////////////////////////////////////////
//
// Helper Fuctions for item.cpp and folder.cpp
//
///////////////////////////////////////////////////////////////////////////////
int _CompareURL(LPMYPIDL pooi1, LPMYPIDL pooi2) { return UrlCompare(URL(&(pooi1->ooe)), URL(&(pooi2->ooe)), TRUE); }
int _CompareShortName(LPMYPIDL pooi1, LPMYPIDL pooi2) { PCTSTR pszNameLocal1; PCTSTR pszNameLocal2;
LPTSTR szNameUnaligned1 = NAME(&(pooi1->ooe)); LPTSTR szNameUnaligned2 = NAME(&(pooi2->ooe));
TSTR_ALIGNED_STACK_COPY( &pszNameLocal1, szNameUnaligned1 ); TSTR_ALIGNED_STACK_COPY( &pszNameLocal2, szNameUnaligned2 );
return StrCmp( pszNameLocal1, pszNameLocal2 ); }
int _CompareLastUpdate(LPMYPIDL pooi1, LPMYPIDL pooi2) { if (pooi1->ooe.m_LastUpdated - pooi2->ooe.m_LastUpdated > 0) return 1; return -1; }
int _CompareCookie(REFCLSID cookie1, REFCLSID cookie2) { return memcmp(&cookie1, &cookie2, sizeof(CLSID)); }
int _CompareStatus(LPMYPIDL pooi1, LPMYPIDL pooi2) { return StrCmp(STATUS(&(pooi1->ooe)), STATUS(&(pooi2->ooe))); }
int _CompareIdentities(LPMYPIDL pooi1, LPMYPIDL pooi2) { if (pooi1->ooe.clsidDest != pooi2->ooe.clsidDest) return -1;
if (!IsNativeAgent(pooi1->ooe.clsidDest)) return _CompareCookie(pooi1->ooe.m_Cookie, pooi2->ooe.m_Cookie);
return _CompareURL(pooi1, pooi2); }
BOOL _ValidateIDListArray(UINT cidl, LPCITEMIDLIST *ppidl) { UINT i;
for (i = 0; i < cidl; i++) { if (!IS_VALID_MYPIDL(ppidl[i])) return FALSE; }
return TRUE; }
int _LaunchApp(HWND hwnd, LPCTSTR pszPath) { SHELLEXECUTEINFO ei = { 0 };
ei.cbSize = sizeof(SHELLEXECUTEINFO); ei.hwnd = hwnd; ei.lpFile = pszPath; ei.nShow = SW_SHOWNORMAL;
return ShellExecuteEx(&ei); }
void _GenerateEvent(LONG lEventId, LPITEMIDLIST pidlIn, LPITEMIDLIST pidlNewIn, BOOL bRefresh) { LPITEMIDLIST pidlFolder = GetSubscriptionFolderPidl(); if (!pidlFolder) return;
LPITEMIDLIST pidl = ILCombine(pidlFolder, pidlIn); if (pidl) { if (pidlNewIn) { LPITEMIDLIST pidlNew = ILCombine(pidlFolder, pidlNewIn); if (pidlNew) { SHChangeNotify(lEventId, SHCNF_IDLIST, pidl, pidlNew); ILFree(pidlNew); } } else { SHChangeNotify(lEventId, SHCNF_IDLIST, pidl, NULL); } if (bRefresh) SHChangeNotifyHandleEvents(); ILFree(pidl); } }
BOOL _InitComCtl32() { static BOOL fInitialized = FALSE;
if (!fInitialized) { INITCOMMONCONTROLSEX icc;
icc.dwSize = sizeof(INITCOMMONCONTROLSEX); icc.dwICC = ICC_NATIVEFNTCTL_CLASS | ICC_DATE_CLASSES; fInitialized = InitCommonControlsEx(&icc); } return fInitialized; }
const struct { LPCSTR pszVerb; UINT idCmd; } rgcmds[] = { { c_szOpen, RSVIDM_OPEN }, { c_szCopy, RSVIDM_COPY }, { c_szRename, RSVIDM_RENAME}, { c_szPaste, RSVIDM_PASTE}, { c_szDelete, RSVIDM_DELETE }, { c_szProperties, RSVIDM_PROPERTIES } };
int _GetCmdID(LPCSTR pszCmd) { if (HIWORD(pszCmd)) { int i; for (i = 0; i < ARRAYSIZE(rgcmds); i++) { if (lstrcmpiA(rgcmds[i].pszVerb, pszCmd) == 0) { return rgcmds[i].idCmd; } }
return -1; // unknown
} return (int)LOWORD(pszCmd); }
BOOL CALLBACK _AddOnePropSheetPage(HPROPSHEETPAGE hpage, LPARAM lParam) { PROPSHEETHEADER * ppsh = (PROPSHEETHEADER *) lParam;
if (ppsh->nPages < MAX_PROP_PAGES) { ppsh->phpage[ppsh->nPages++] = hpage; return TRUE; } return FALSE; }
HRESULT _CreatePropSheet(HWND hwnd, POOEBuf pBuf) { ASSERT(pBuf);
ISubscriptionMgr * pSub= NULL; HRESULT hr = CoInitialize(NULL); RETURN_ON_FAILURE(hr);
hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr, (void **)&pSub); CoUninitialize(); RETURN_ON_FAILURE(hr); ASSERT(pSub);
BSTR bstrURL = NULL; hr = CreateBSTRFromTSTR(&bstrURL, pBuf->m_URL); if (S_OK == hr) hr = pSub->ShowSubscriptionProperties(bstrURL, hwnd); SAFERELEASE(pSub); SAFEFREEBSTR(bstrURL); return hr; }
// Note:
// We return FALSE on illegal DATE data.
BOOL DATE2DateTimeString(CFileTime& ft, LPTSTR pszText, int cchText) { SYSTEMTIME st;
if (ft == 0) { if (szUnknown[0] == 0) MLLoadString(IDS_UNKNOWN, szUnknown, ARRAYSIZE(szUnknown));
StrCpyN(pszText, szUnknown, cchText); return FALSE; }
if (!FileTimeToSystemTime(&ft, &st)) { if (szNone[0] == 0) MLLoadString(IDS_NONE, szNone, ARRAYSIZE(szNone));
StrCpyN(pszText, szNone, cchText); return FALSE; } GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, &st, NULL, pszText, cchText); StrCatBuff(pszText, L" ", cchText);
int nLen = lstrlen(pszText);
if (nLen >= cchText) { return FALSE; } pszText += nLen; GetTimeFormat(LOCALE_USER_DEFAULT, TIME_NOSECONDS, &st, NULL, pszText, cchText - nLen); return TRUE; }
void CopyToOOEBuf(POOEntry pooe, POOEBuf pBuf) { ASSERT(pooe); ASSERT(pBuf);
pBuf->dwFlags = pooe->dwFlags; pBuf->m_LastUpdated = pooe->m_LastUpdated; pBuf->m_NextUpdate = pooe->m_NextUpdate; pBuf->m_SizeLimit = pooe->m_SizeLimit; pBuf->m_ActualSize = pooe->m_ActualSize; pBuf->m_RecurseLevels = pooe->m_RecurseLevels; pBuf->m_RecurseFlags = pooe->m_RecurseFlags; pBuf->m_Priority = pooe->m_Priority; pBuf->bDesktop = pooe->bDesktop; pBuf->bChannel = pooe->bChannel; pBuf->bMail = pooe->bMail; pBuf->bGleam = pooe->bGleam; pBuf->bChangesOnly = pooe->bChangesOnly; pBuf->fChannelFlags = pooe->fChannelFlags; pBuf->bNeedPassword = pooe->bNeedPassword; pBuf->m_Cookie = pooe->m_Cookie; pBuf->groupCookie = pooe->groupCookie; pBuf->grfTaskTrigger = pooe->grfTaskTrigger; pBuf->m_Trigger = pooe->m_Trigger; pBuf->clsidDest = pooe->clsidDest; pBuf->status = pooe->status;
StrCpyN(pBuf->m_URL, URL(pooe), ARRAYSIZE(pBuf->m_URL)); StrCpyN(pBuf->m_Name, NAME(pooe), ARRAYSIZE(pBuf->m_Name)); StrCpyN(pBuf->username, UNAME(pooe), ARRAYSIZE(pBuf->username)); StrCpyN(pBuf->password, PASSWD(pooe), ARRAYSIZE(pBuf->password)); StrCpyN(pBuf->statusStr, STATUS(pooe), ARRAYSIZE(pBuf->statusStr)); }
void CopyToMyPooe(POOEBuf pBuf, POOEntry pooe) { UINT offset = sizeof(OOEntry); UINT srcLen = lstrlen(pBuf->m_URL) + 1;
ASSERT(pooe); ASSERT(pBuf);
pooe->dwFlags = pBuf->dwFlags; pooe->m_LastUpdated = pBuf->m_LastUpdated; pooe->m_NextUpdate = pBuf->m_NextUpdate; pooe->m_SizeLimit = pBuf->m_SizeLimit; pooe->m_ActualSize = pBuf->m_ActualSize; pooe->m_RecurseLevels = pBuf->m_RecurseLevels; pooe->m_Priority = pBuf->m_Priority; pooe->m_RecurseFlags = pBuf->m_RecurseFlags; pooe->bDesktop = pBuf->bDesktop; pooe->bChannel = pBuf->bChannel; pooe->bMail = pBuf->bMail; pooe->bGleam = pBuf->bGleam; pooe->bChangesOnly = pBuf->bChangesOnly; pooe->fChannelFlags = pBuf->fChannelFlags; pooe->bNeedPassword = pBuf->bNeedPassword; pooe->m_Cookie = pBuf->m_Cookie; pooe->groupCookie = pBuf->groupCookie; pooe->m_Trigger = pBuf->m_Trigger; pooe->grfTaskTrigger = pBuf->grfTaskTrigger; pooe->clsidDest = pBuf->clsidDest; pooe->status = pBuf->status;
pooe->m_URL = (LPTSTR)((LPBYTE)pooe + offset); srcLen = lstrlen(pBuf->m_URL) + 1; StrCpyN(pooe->m_URL, pBuf->m_URL, srcLen); offset += srcLen * sizeof (TCHAR); pooe->m_URL = (LPTSTR) PtrDifference(pooe->m_URL, pooe);
pooe->m_Name = (LPTSTR)((LPBYTE)pooe + offset); srcLen = lstrlen(pBuf->m_Name) + 1; StrCpyN(pooe->m_Name, pBuf->m_Name, srcLen); offset += srcLen * sizeof (TCHAR); pooe->m_Name = (LPTSTR) PtrDifference(pooe->m_Name, pooe);
pooe->username = (LPTSTR)((LPBYTE)pooe + offset); srcLen = lstrlen(pBuf->username) + 1; StrCpyN(pooe->username, pBuf->username, srcLen); offset += srcLen * sizeof (TCHAR); pooe->username = (LPTSTR) PtrDifference(pooe->username, pooe);
pooe->password = (LPTSTR)((LPBYTE)pooe + offset); srcLen = lstrlen(pBuf->password) + 1; StrCpyN(pooe->password, pBuf->password, srcLen); offset += srcLen * sizeof (TCHAR); pooe->password = (LPTSTR) PtrDifference(pooe->password, pooe);
pooe->statusStr = (LPTSTR)((LPBYTE)pooe + offset); srcLen = lstrlen(pBuf->statusStr) + 1; StrCpyN(pooe->statusStr, pBuf->statusStr, srcLen); offset += srcLen * sizeof (TCHAR); pooe->statusStr = (LPTSTR) PtrDifference(pooe->statusStr, pooe);
pooe->dwSize = offset; }
UINT BufferSize(POOEBuf pBuf) { UINT strLen = 0; ASSERT(pBuf);
strLen += lstrlen(pBuf->m_URL) + 1; strLen += lstrlen(pBuf->m_Name) + 1; strLen += lstrlen(pBuf->username) + 1; strLen += lstrlen(pBuf->password) + 1; strLen += lstrlen(pBuf->statusStr) + 1;
return strLen * sizeof(TCHAR); }
typedef struct { int cItems; LPCTSTR pszName; LPCTSTR pszUrl; } DELETE_CONFIRM_INFO;
INT_PTR CALLBACK ConfirmDeleteDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam) {
switch(message) {
case WM_INITDIALOG: { DELETE_CONFIRM_INFO* pInfo = (DELETE_CONFIRM_INFO*)lParam; ASSERT (pInfo); ASSERT(pInfo->cItems == 1);
SetListViewToString (GetDlgItem (hDlg, IDC_NAME), pInfo->pszName); SetListViewToString (GetDlgItem (hDlg, IDC_LOCATION), pInfo->pszUrl); } break;
case WM_COMMAND: switch(LOWORD(wParam)) { case IDYES: case IDNO: case IDCANCEL: EndDialog(hDlg, wParam); break; } break;
case WM_NOTIFY: if (LOWORD(wParam) == IDC_LOCATION) { NM_LISTVIEW * pnmlv = (NM_LISTVIEW *)lParam; ASSERT(pnmlv); 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_LOCATION), &lvi)) return FALSE;
NMLVGETINFOTIP * pTip = (NMLVGETINFOTIP *)pnmlv; ASSERT(pTip->pszText); StrCpyN(pTip->pszText, szURL, pTip->cchTextMax); return TRUE; } } return FALSE;
default: return FALSE;
} // end of switch
return TRUE; }
BOOL ConfirmDelete(HWND hwnd, UINT cItems, LPMYPIDL * ppidl) { ASSERT(ppidl); INT_PTR iRet;
// Check if the user is restricted from deleting URLs.
// If they're deleting multiple, we'll fail if any can fail.
UINT i; for (i = 0; i < cItems; i++) { if (ppidl[i]->ooe.bChannel) { if (SHRestricted2(REST_NoRemovingChannels, URL(&(ppidl[i]->ooe)), 0)) { if (IsWindow(hwnd)) SGMessageBox(hwnd, IDS_RESTRICTED, MB_OK); return FALSE; } }
if (!ppidl[i]->ooe.bDesktop) { // FEATURE: What about desktop components?
if (SHRestricted2(REST_NoRemovingSubscriptions, URL(&(ppidl[i]->ooe)), 0)) { if (IsWindow(hwnd)) SGMessageBox(hwnd, IDS_RESTRICTED, MB_OK); return FALSE; } } }
if (IsWindow(hwnd)) { DELETE_CONFIRM_INFO dci = {0}; dci.cItems = cItems; if (cItems == 1) { dci.pszName = NAME(&(ppidl[0]->ooe)); dci.pszUrl = URL(&(ppidl[0]->ooe)); iRet = DialogBoxParam(MLGetHinst(), MAKEINTRESOURCE(IDD_OBJECTDEL_WARNING), hwnd, ConfirmDeleteDlgProc, (LPARAM)&dci); } else {
TCHAR szFormat[200]; // Enough room for format string and int as string
TCHAR szBuf[ARRAYSIZE(szFormat) + 11];
MLLoadString(IDS_DEL_MULTIPLE_FMT, szFormat, ARRAYSIZE(szFormat)); wnsprintf(szBuf, ARRAYSIZE(szBuf), szFormat, cItems);
MLLoadString(IDS_DELETE_CAPTION, szFormat, ARRAYSIZE(szFormat));
MSGBOXPARAMS mbp;
mbp.cbSize = sizeof(MSGBOXPARAMS); mbp.hwndOwner = hwnd; mbp.hInstance = MLGetHinst(); mbp.lpszText = szBuf; mbp.lpszCaption = szFormat; mbp.dwStyle = MB_YESNO | MB_USERICON; mbp.lpszIcon = MAKEINTRESOURCE(IDI_OBJECTDELETED); iRet = MessageBoxIndirect(&mbp); } if (iRet == IDYES) return TRUE; return FALSE; } else { return TRUE; } }
BOOL IsHTTPPrefixed(LPCTSTR szURL) { TCHAR szCanonicalURL[MAX_URL]; DWORD dwSize = MAX_URL; URL_COMPONENTS uc;
memset(&uc, 0, sizeof(URL_COMPONENTS)); uc.dwStructSize = sizeof(URL_COMPONENTS);
// Note: We explicitly check for and allow the "about:home" URL to pass through here. This allows
// the Active Desktop "My Current Home Page" component to specify that URL when creating and managing
// it's subscription which is consistent with it's use of that form in the browser.
if (!InternetCanonicalizeUrl(szURL, szCanonicalURL, &dwSize, ICU_DECODE) || !InternetCrackUrl(szCanonicalURL, 0, 0, &uc) || ((INTERNET_SCHEME_HTTP != uc.nScheme) && (INTERNET_SCHEME_HTTPS != uc.nScheme) && (0 != StrCmpI(TEXT("about:home"), szURL)))) { return FALSE; } return TRUE; }
// Checks if global state is offline
BOOL IsGlobalOffline(void) { DWORD dwState = 0, dwSize = sizeof(DWORD); BOOL fRet = FALSE; HANDLE hModuleHandle = LoadLibraryA("wininet.dll");
if(!hModuleHandle) return FALSE;
if(InternetQueryOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &dwState, &dwSize)) { if(dwState & INTERNET_STATE_DISCONNECTED_BY_USER) fRet = TRUE; }
return fRet; }
void SetGlobalOffline(BOOL fOffline) { INTERNET_CONNECTED_INFO ci;
memset(&ci, 0, sizeof(ci)); if(fOffline) { ci.dwConnectedState = INTERNET_STATE_DISCONNECTED_BY_USER; ci.dwFlags = ISO_FORCE_DISCONNECTED; } else { ci.dwConnectedState = INTERNET_STATE_CONNECTED; }
InternetSetOption(NULL, INTERNET_OPTION_CONNECTED_STATE, &ci, sizeof(ci)); }
//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 WCMessageBox(HWND hwnd, UINT idTextFmt, UINT idCaption, UINT uType, ...) { TCHAR szCaption[256]; TCHAR szTextFmt[512]; LPTSTR pszText; int result; va_list va;
va_start(va, uType);
szCaption[0] = 0;
MLLoadString(idTextFmt, szTextFmt, ARRAYSIZE(szTextFmt));
if (idCaption <= 0) { if (NULL != hwnd) { GetWindowText(hwnd, szCaption, ARRAYSIZE(szCaption)); }
// This handles GetWindowText failure and a NULL hwnd
if (0 == szCaption[0]) { #if IDS_DEFAULT_MSG_CAPTION < 1
#error IDS_DEFAULT_MSG_CAPTION is defined incorrectly
#endif
idCaption = IDS_DEFAULT_MSG_CAPTION; } }
if (idCaption > 0) { MLLoadString(idCaption, szCaption, ARRAYSIZE(szCaption)); }
ASSERT(0 != szCaption[0]);
if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_STRING, szTextFmt, 0, 0, (LPTSTR)&pszText, 0, &va)) { result = MessageBox(hwnd, pszText, szCaption, uType); LocalFree(pszText); } else { // FormatMessage failed. Oh well. Guess we'll just ask the question
// with the format string. Sure it's ugly but it's better than picking a
// totally random return value.
result = MessageBox(hwnd, szTextFmt, szCaption, uType); }
return result; }
/////////////////////////////////////////////////////////////////////////////
// SGMessageBox
/////////////////////////////////////////////////////////////////////////////
int SGMessageBox ( HWND hwndParent, UINT idStringRes, UINT uType ) { ASSERT(hwndParent != NULL); ASSERT(IsWindow(hwndParent));
TCHAR szError[512]; if (!MLLoadString(idStringRes, szError, ARRAYSIZE(szError))) return 0;
TCHAR szTitle[128]; szTitle[0] = 0;
if (hwndParent != NULL) GetWindowText(hwndParent, szTitle, ARRAYSIZE(szTitle));
return MessageBox( hwndParent, szError, ((hwndParent != NULL) ? szTitle : NULL), uType); }
#ifdef DEBUG
/////////////////////////////////////////////////////////////////////////////
// DumpTaskTrigger
/////////////////////////////////////////////////////////////////////////////
void DumpTaskTrigger ( TASK_TRIGGER * pTT ) { TraceMsg(TF_DUMPTRIGGER, "----- BEGIN DumpTaskTrigger -----");
TraceMsg(TF_DUMPTRIGGER, "cbTriggerSize = %d", pTT->cbTriggerSize); TraceMsg(TF_DUMPTRIGGER, "Reserved1 = %d", pTT->Reserved1); TraceMsg(TF_DUMPTRIGGER, "wBeginYear = %d", pTT->wBeginYear); TraceMsg(TF_DUMPTRIGGER, "wBeginMonth = %d", pTT->wBeginMonth); TraceMsg(TF_DUMPTRIGGER, "wBeginDay = %d", pTT->wBeginDay); TraceMsg(TF_DUMPTRIGGER, "wEndYear = %d", pTT->wEndYear); TraceMsg(TF_DUMPTRIGGER, "wEndMonth = %d", pTT->wEndMonth); TraceMsg(TF_DUMPTRIGGER, "wEndDay = %d", pTT->wEndDay); TraceMsg(TF_DUMPTRIGGER, "wStartHour = %d", pTT->wStartHour); TraceMsg(TF_DUMPTRIGGER, "wStartMinute = %d", pTT->wStartMinute); TraceMsg(TF_DUMPTRIGGER, "MinutesDuration = %d", pTT->MinutesDuration); TraceMsg(TF_DUMPTRIGGER, "MinutesInterval = %d", pTT->MinutesInterval); TraceMsg(TF_DUMPTRIGGER, "rgFlags = %d", pTT->rgFlags); TraceMsg(TF_DUMPTRIGGER, "Reserved2 = %d", pTT->Reserved2); TraceMsg(TF_DUMPTRIGGER, "wRandomMinutesInterval = %d", pTT->wRandomMinutesInterval);
switch (pTT->TriggerType) { case TASK_TIME_TRIGGER_DAILY: { TraceMsg(TF_DUMPTRIGGER, "DAILY"); TraceMsg(TF_DUMPTRIGGER, "DaysInterval = %d", pTT->Type.Daily.DaysInterval); break; }
case TASK_TIME_TRIGGER_WEEKLY: { TraceMsg(TF_DUMPTRIGGER, "WEEKLY"); TraceMsg(TF_DUMPTRIGGER, "WeeksInterval = %d", pTT->Type.Weekly.WeeksInterval); TraceMsg(TF_DUMPTRIGGER, "rgfDaysOfTheWeek = %d", pTT->Type.Weekly.rgfDaysOfTheWeek); break; }
case TASK_TIME_TRIGGER_MONTHLYDATE: { TraceMsg(TF_DUMPTRIGGER, "MONTHLY DATE"); TraceMsg(TF_DUMPTRIGGER, "rgfDays = %d", pTT->Type.MonthlyDate.rgfDays); TraceMsg(TF_DUMPTRIGGER, "rgfMonths = %d", pTT->Type.MonthlyDate.rgfMonths); break; }
case TASK_TIME_TRIGGER_MONTHLYDOW: { TraceMsg(TF_DUMPTRIGGER, "MONTHLY DOW"); TraceMsg(TF_DUMPTRIGGER, "wWhichWeek = %d", pTT->Type.MonthlyDOW.wWhichWeek); TraceMsg(TF_DUMPTRIGGER, "rgfDaysOfTheWeek = %d", pTT->Type.MonthlyDOW.rgfDaysOfTheWeek); TraceMsg(TF_DUMPTRIGGER, "rgfMonths = %d", pTT->Type.MonthlyDOW.rgfMonths); break; }
default: { ASSERT(FALSE); break; } }
TraceMsg(TF_DUMPTRIGGER, "----- END DumpTaskTrigger -----"); } #endif // DEBUG
|