You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
2597 lines
78 KiB
2597 lines
78 KiB
#include "precomp.h"
|
|
#include <olectl.h>
|
|
|
|
// Implementation helper structures/routines declarations
|
|
typedef struct tagFAVLIST {
|
|
LPFAVSTRUC pfs;
|
|
int cElements;
|
|
} FAVLIST, (FAR *LPFAVLIST);
|
|
|
|
typedef struct tagPERCONTROLDATA {
|
|
FAVLIST flFavorites;
|
|
FAVLIST flQuickLinks;
|
|
} PERCONTROLDATA, (FAR *LPPERCONTROLDATA);
|
|
|
|
typedef struct tagAEFAVPARAMS {
|
|
LPFAVSTRUC pfs;
|
|
BOOL fQL;
|
|
|
|
HWND hwndErrorParent;
|
|
HWND htv;
|
|
HTREEITEM hti;
|
|
LPCTSTR pszExtractPath;
|
|
LPCTSTR pszPrevExtractPath;
|
|
|
|
DWORD dwPlatformID;
|
|
DWORD dwMode;
|
|
} AEFAVPARAMS, (FAR *LPAEFAVPARAMS);
|
|
|
|
static BOOL migrateFavoritesHelper(LPCTSTR pszIns);
|
|
static void migrateToOldFavoritesHelper(LPCTSTR pszIns);
|
|
static int importFavoritesHelper(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns,
|
|
LPCTSTR pszFixPath, LPCTSTR pszNewPath, BOOL fIgnoreOffline);
|
|
static int importQuickLinksHelper(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns,
|
|
LPCTSTR pszFixPath, LPCTSTR pszNewPath, BOOL fIgnoreOffline);
|
|
static BOOL newUrlHelper(HWND htv, LPCTSTR pszExtractPath, DWORD dwPlatformID, DWORD dwMode);
|
|
static BOOL modifyFavoriteHelper(HWND htv, HTREEITEM hti, LPCTSTR pszExtractPath, LPCTSTR pszPrevExtractPath,
|
|
DWORD dwPlatformID, DWORD dwMode);
|
|
static BOOL deleteFavoriteHelper(HWND htv, HTREEITEM hti, LPCTSTR pszExtractPath);
|
|
static int importFavoritesCmdHelper(HWND htv, LPCTSTR pszExtractPath);
|
|
static void exportFavoritesHelper(HWND htv, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath = TRUE);
|
|
static void exportQuickLinksHelper(HWND htv, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath = TRUE);
|
|
static void getFavoritesInfoTipHelper(LPNMTVGETINFOTIP pGetInfoTip);
|
|
static BOOL getFavoriteUrlHelper(HWND htv, HTREEITEM hti, LPTSTR pszUrl);
|
|
|
|
static int importItems(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns, LPCTSTR pszFixPath, LPCTSTR pszNewPath,
|
|
BOOL fIgnoreOffline, BOOL fQL = FALSE);
|
|
|
|
static INT_PTR CALLBACK addEditFavoriteDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
|
|
|
|
static LPFAVSTRUC getItem (HWND htv, HTREEITEM hti);
|
|
static LPFAVSTRUC getFolderItem (HWND htv, HTREEITEM hti);
|
|
static LPFAVSTRUC findByName (HWND htv, HTREEITEM hti, LPCTSTR pszName);
|
|
static LPFAVSTRUC findPath (HWND htv, HTREEITEM hti, LPCTSTR pszFolders);
|
|
static HRESULT isFavoriteItem(HWND htv, HTREEITEM hti);
|
|
|
|
static LPFAVSTRUC createFolderItems(HWND htv, HTREEITEM hti, LPCTSTR pszFolders);
|
|
static BOOL importPath (HWND htv, HTREEITEM htiFrom, HTREEITEM *phtiAfter);
|
|
static void importPath (HWND htv, HTREEITEM hti, LPCTSTR pszFilesPath, LPCTSTR pszExtractPath, LPCTSTR pszReserved = NULL);
|
|
static int exportItems(HWND htv, HTREEITEM hti, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath = TRUE);
|
|
|
|
BOOL extractIcon(LPCTSTR pszIconFile, int iIconIndex, LPCTSTR pszExtractPath, LPTSTR pszResult, UINT cchResult);
|
|
static LPCTSTR getLinksPath(LPTSTR pszPath, UINT cchPath = 0);
|
|
|
|
static LPTSTR encodeFavName(LPTSTR pszFavName, LPCTSTR pszIns);
|
|
static LPTSTR decodeFavName(LPTSTR pszFavName, LPCTSTR pszIns);
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// SFav constructors and destructors
|
|
|
|
SFav::SFav()
|
|
{
|
|
wType = FTYPE_UNUSED;
|
|
|
|
pszName = NULL;
|
|
pszPath = NULL;
|
|
pszUrl = NULL;
|
|
pszIconFile = NULL;
|
|
fOffline = FALSE;
|
|
|
|
pTvItem = NULL;
|
|
}
|
|
|
|
SFav::~SFav()
|
|
{
|
|
Delete();
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// SFav properties
|
|
|
|
HRESULT SFav::Load(UINT nIndex, LPCTSTR pszIns, BOOL fQL /*= FALSE*/,
|
|
LPCTSTR pszFixPath /*= NULL*/, LPCTSTR pszNewPath /*= NULL*/, BOOL fIgnoreOffline /*= FALSE*/)
|
|
{
|
|
TCHAR szKey[32];
|
|
LPCTSTR pszSection, pszKeyFmt;
|
|
|
|
if (pszIns == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
if (!fQL) {
|
|
pszSection = IS_FAVORITESEX;
|
|
pszKeyFmt = IK_TITLE_FMT;
|
|
}
|
|
else {
|
|
pszSection = IS_URL;
|
|
pszKeyFmt = IK_QUICKLINK_NAME;
|
|
}
|
|
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
if (InsIsKeyEmpty(pszSection, szKey, pszIns))
|
|
return S_FALSE;
|
|
|
|
wType = FTYPE_URL;
|
|
if (!Expand())
|
|
return E_OUTOFMEMORY;
|
|
|
|
// Title
|
|
pszKeyFmt = (!fQL ? IK_TITLE_FMT : IK_QUICKLINK_NAME);
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
InsGetString(pszSection, szKey, pszName, MAX_PATH, pszIns);
|
|
if (*pszName == TEXT('\0'))
|
|
goto Fail;
|
|
|
|
// URL
|
|
pszKeyFmt = (!fQL ? IK_URL_FMT : IK_QUICKLINK_URL);
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
InsGetString(pszSection, szKey, pszUrl, INTERNET_MAX_URL_LENGTH, pszIns);
|
|
if (*pszUrl == TEXT('\0'))
|
|
goto Fail;
|
|
|
|
// Icon file (never required)
|
|
pszKeyFmt = (!fQL ? IK_ICON_FMT : IK_QUICKLINK_ICON);
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
InsGetString(pszSection, szKey, pszIconFile, INTERNET_MAX_URL_LENGTH, pszIns);
|
|
|
|
if (*pszIconFile != TEXT('\0') && !PathIsURL(pszIconFile)) {
|
|
BOOL fTryToFix;
|
|
|
|
fTryToFix = FALSE;
|
|
if (pszFixPath == NULL)
|
|
fTryToFix = TRUE;
|
|
|
|
else
|
|
if (PathIsPrefix(pszFixPath, pszIconFile))
|
|
fTryToFix = !PathFileExists(pszIconFile);
|
|
|
|
if (fTryToFix && pszNewPath != NULL) {
|
|
TCHAR szNewPath[MAX_PATH];
|
|
|
|
PathCombine(szNewPath, pszNewPath, PathFindFileName(pszIconFile));
|
|
StrCpy(pszIconFile, szNewPath);
|
|
if (!PathFileExists(pszIconFile))
|
|
*pszIconFile = TEXT('\0');
|
|
}
|
|
}
|
|
|
|
// Make available offline flag
|
|
fOffline = FALSE;
|
|
if (!fIgnoreOffline) {
|
|
pszKeyFmt = (!fQL ? IK_OFFLINE_FMT : IK_QUICKLINK_OFFLINE);
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
fOffline = InsGetBool(pszSection, szKey, FALSE, pszIns);
|
|
}
|
|
|
|
SetTVI();
|
|
Shrink();
|
|
return S_OK;
|
|
|
|
Fail:
|
|
Delete();
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT SFav::Load(LPCTSTR pszName, LPCTSTR pszFavorite, LPCTSTR pszExtractPath,
|
|
ISubscriptionMgr2 *psm /*= NULL*/, BOOL fIgnoreOffline /*= FALSE*/)
|
|
{
|
|
TCHAR szIconFile[INTERNET_MAX_URL_LENGTH];
|
|
|
|
USES_CONVERSION;
|
|
|
|
if (pszFavorite == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
wType = FTYPE_URL;
|
|
if (!Expand())
|
|
return E_OUTOFMEMORY;
|
|
|
|
// Title
|
|
if (pszName == NULL)
|
|
pszName = PathFindFileName(pszFavorite);
|
|
else
|
|
ASSERT(StrStrI(pszFavorite, pszName) != NULL);
|
|
StrCpy(SFav::pszName, pszName);
|
|
PathRenameExtension(SFav::pszName, DOT_URL);
|
|
|
|
// URL
|
|
InsGetString(IS_INTERNETSHORTCUT, IK_URL, pszUrl, INTERNET_MAX_URL_LENGTH, pszFavorite);
|
|
if (*pszUrl == TEXT('\0'))
|
|
goto Fail;
|
|
|
|
// Icon file
|
|
InsGetString(IS_INTERNETSHORTCUT, IK_ICONFILE, szIconFile, countof(szIconFile), pszFavorite);
|
|
if (szIconFile[0] != TEXT('\0')) {
|
|
int iIconIndex;
|
|
|
|
iIconIndex = GetPrivateProfileInt(IS_INTERNETSHORTCUT, IK_ICONINDEX, 1, pszFavorite);
|
|
::extractIcon(szIconFile, iIconIndex, pszExtractPath, pszIconFile, INTERNET_MAX_URL_LENGTH);
|
|
}
|
|
|
|
// Make available offline flag
|
|
fOffline = FALSE;
|
|
if (!fIgnoreOffline) {
|
|
HRESULT hr;
|
|
BOOL fOwnSubMgr;
|
|
|
|
fOwnSubMgr = FALSE;
|
|
if (psm == NULL) {
|
|
hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr2, (LPVOID *)&psm);
|
|
if (SUCCEEDED(hr))
|
|
fOwnSubMgr = TRUE;
|
|
}
|
|
|
|
if (psm != NULL) {
|
|
hr = psm->IsSubscribed(T2W(pszUrl), &fOffline);
|
|
if (FAILED(hr))
|
|
fOffline = FALSE;
|
|
}
|
|
|
|
if (fOwnSubMgr)
|
|
psm->Release();
|
|
}
|
|
|
|
SetTVI();
|
|
Shrink();
|
|
return S_OK;
|
|
|
|
Fail:
|
|
Delete();
|
|
return E_FAIL;
|
|
}
|
|
|
|
HRESULT SFav::Add(HWND htv, HTREEITEM hti)
|
|
{
|
|
SFav *pfsFolder;
|
|
TV_INSERTSTRUCT tvins;
|
|
HTREEITEM htiParent;
|
|
|
|
if (hti == NULL)
|
|
hti = TreeView_GetSelection(htv);
|
|
|
|
pfsFolder = NULL;
|
|
if (wType == FTYPE_URL) {
|
|
TCHAR szFolders[MAX_PATH];
|
|
LPTSTR pszFile;
|
|
|
|
pszFile = PathFindFileName(pszName);
|
|
if (pszFile > pszName) {
|
|
*(pszFile-1) = TEXT('\0');
|
|
StrCpy(szFolders, pszName);
|
|
StrCpy(pszName, pszFile);
|
|
|
|
pfsFolder = ::createFolderItems(htv, hti, szFolders);
|
|
if (pfsFolder == NULL)
|
|
goto Fail;
|
|
}
|
|
}
|
|
|
|
SetTVI();
|
|
|
|
if (pfsFolder == NULL)
|
|
pfsFolder = ::getFolderItem(htv, hti);
|
|
if (pfsFolder != NULL) {
|
|
if (pfsFolder->pTvItem == NULL || pfsFolder->pTvItem->hItem == NULL)
|
|
goto Fail;
|
|
|
|
htiParent = pfsFolder->pTvItem->hItem;
|
|
}
|
|
else
|
|
htiParent = TVI_ROOT;
|
|
|
|
ZeroMemory(&tvins, sizeof(tvins));
|
|
tvins.hParent = htiParent;
|
|
tvins.hInsertAfter = TVI_LAST;
|
|
|
|
CopyMemory(&tvins.item, pTvItem, sizeof(TV_ITEM));
|
|
pTvItem->hItem = TreeView_InsertItem(htv, &tvins);
|
|
|
|
pTvItem->mask = TVIF_HANDLE | TVIF_STATE;
|
|
TreeView_GetItem(htv, pTvItem);
|
|
|
|
if (pfsFolder != NULL)
|
|
TreeView_Expand(htv, htiParent, TVE_EXPAND);
|
|
|
|
TreeView_SelectItem(htv, pTvItem->hItem);
|
|
|
|
//----- Increment the number of items -----
|
|
LPPERCONTROLDATA ppcd;
|
|
LPFAVLIST pfl;
|
|
|
|
ppcd = (LPPERCONTROLDATA)GetWindowLongPtr(htv, GWLP_USERDATA);
|
|
ASSERT (NULL != ppcd);
|
|
|
|
pfl = (S_OK == ::isFavoriteItem(htv, pTvItem->hItem)) ? &ppcd->flFavorites : &ppcd->flQuickLinks;
|
|
pfl->cElements++;
|
|
|
|
return S_OK;
|
|
|
|
Fail:
|
|
Delete();
|
|
return FALSE;
|
|
}
|
|
|
|
// NOTE: (andrewgu) can also be used to clear the entry in case of quick links
|
|
HRESULT SFav::Save(HWND htv, UINT nIndex, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fQL /*= FALSE*/,
|
|
BOOL fFixUpPath /*= TRUE*/)
|
|
{
|
|
TCHAR szAux[INTERNET_MAX_URL_LENGTH],
|
|
szKey[32];
|
|
LPCTSTR pszSection, pszKeyFmt,
|
|
pszAux;
|
|
|
|
if (pszIns == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
// Name
|
|
if (!fQL) {
|
|
if (wType != FTYPE_URL)
|
|
return E_UNEXPECTED;
|
|
|
|
GetPath(htv, szAux);
|
|
PathAppend(szAux, pszName);
|
|
|
|
if (!PathIsExtension(szAux, DOT_URL))
|
|
StrCat(szAux, DOT_URL);
|
|
|
|
pszAux = szAux;
|
|
ASSERT(*pszAux != TEXT('\0'));
|
|
|
|
pszSection = IS_FAVORITESEX;
|
|
pszKeyFmt = IK_TITLE_FMT;
|
|
}
|
|
else {
|
|
if (pszName != NULL && wType != FTYPE_URL)
|
|
return E_UNEXPECTED;
|
|
|
|
pszAux = NULL;
|
|
if (pszName != NULL) {
|
|
StrCpy(szAux, pszName);
|
|
|
|
if (!PathIsExtension(szAux, DOT_URL))
|
|
StrCat(szAux, DOT_URL);
|
|
|
|
pszAux = szAux;
|
|
ASSERT(*pszAux != TEXT('\0'));
|
|
}
|
|
|
|
pszSection = IS_URL;
|
|
pszKeyFmt = IK_QUICKLINK_NAME;
|
|
}
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
WritePrivateProfileString(pszSection, szKey, pszAux, pszIns);
|
|
|
|
// URL
|
|
if (!fQL) {
|
|
ASSERT(pszUrl != NULL && *pszUrl != TEXT('\0'));
|
|
|
|
pszKeyFmt = IK_URL_FMT;
|
|
}
|
|
else {
|
|
if (pszName != NULL)
|
|
{ ASSERT(pszUrl != NULL && *pszUrl != TEXT('\0')); }
|
|
|
|
else
|
|
{ ASSERT(pszUrl == NULL); }
|
|
|
|
pszKeyFmt = IK_QUICKLINK_URL;
|
|
}
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
WritePrivateProfileString(pszSection, szKey, pszUrl, pszIns);
|
|
|
|
// Icon file
|
|
if (!fQL) {
|
|
ASSERT(pszIconFile == NULL || *pszIconFile != TEXT('\0'));
|
|
|
|
pszKeyFmt = IK_ICON_FMT;
|
|
}
|
|
else {
|
|
if (pszName != NULL && pszIconFile != NULL)
|
|
{ ASSERT(*pszIconFile != TEXT('\0')); }
|
|
|
|
else
|
|
{ ASSERT(pszIconFile == NULL); }
|
|
|
|
pszKeyFmt = IK_QUICKLINK_ICON;
|
|
}
|
|
|
|
pszAux = NULL;
|
|
if (pszIconFile != NULL) {
|
|
::extractIcon(pszIconFile, 1, pszExtractPath, szAux, countof(szAux));
|
|
if (szAux[0] != TEXT('\0'))
|
|
if (PathIsPrefix(pszExtractPath, szAux))
|
|
pszAux = szAux;
|
|
|
|
else {
|
|
TCHAR szDest[MAX_PATH];
|
|
|
|
ASSERT(PathFileExists(szAux));
|
|
PathCombine(szDest, pszExtractPath, PathFindFileName(szAux));
|
|
CopyFile(szAux, szDest, FALSE);
|
|
SetFileAttributes(szDest, FILE_ATTRIBUTE_NORMAL);
|
|
|
|
// (pritobla): fFixUpPath should be always TRUE if called by the IEAK
|
|
// Wizard or the Profile Manager. The only case when it would
|
|
// be FALSE is when called by OPKWIZ. They want to keep the path
|
|
// to the icon files what the user entered because they don't use our
|
|
// Wizard/ProfMgr logic of temp dirs.
|
|
pszAux = fFixUpPath ? szDest : szAux;
|
|
}
|
|
}
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
WritePrivateProfileString(pszSection, szKey, pszAux, pszIns);
|
|
|
|
// Make available offline flag
|
|
pszAux = NULL;
|
|
pszKeyFmt = !fQL ? IK_OFFLINE_FMT : IK_QUICKLINK_OFFLINE;
|
|
if (!fQL) {
|
|
if (fOffline)
|
|
pszAux = TEXT("1");
|
|
}
|
|
else
|
|
if (pszName != NULL && fOffline)
|
|
pszAux = TEXT("1");
|
|
wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
|
|
WritePrivateProfileString(pszSection, szKey, pszAux, pszIns);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
void SFav::SetTVI()
|
|
{
|
|
if (!Expand(FF_TVI))
|
|
return;
|
|
|
|
if (wType == FTYPE_URL)
|
|
wnsprintf(pTvItem->pszText, MAX_PATH + 3 + INTERNET_MAX_URL_LENGTH, TEXT("%s = %s"), pszName, pszUrl);
|
|
else
|
|
StrCpy(pTvItem->pszText, pszName);
|
|
|
|
pTvItem->cchTextMax = StrLen(pTvItem->pszText) + 1;
|
|
pTvItem->mask = TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_TEXT;
|
|
pTvItem->lParam = (LPARAM)this;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// SFav operations
|
|
|
|
SFav* SFav::CreateNew(HWND htv, BOOL fQL /*= FALSE*/)
|
|
{
|
|
SFav* pfsFirst;
|
|
|
|
pfsFirst = GetFirst(htv, fQL);
|
|
if (pfsFirst == NULL)
|
|
return NULL;
|
|
|
|
for (UINT i = 0; i < SFav::GetMaxNumber(fQL); i++)
|
|
if ((pfsFirst + i)->wType == FTYPE_UNUSED)
|
|
break;
|
|
if (i >= SFav::GetMaxNumber(fQL))
|
|
return NULL;
|
|
|
|
return (pfsFirst + i);
|
|
}
|
|
|
|
SFav* SFav::GetFirst(HWND htv, BOOL fQL /*= FALSE*/)
|
|
{
|
|
LPPERCONTROLDATA ppcd;
|
|
LPFAVLIST pfl;
|
|
|
|
ppcd = (LPPERCONTROLDATA)GetWindowLongPtr(htv, GWLP_USERDATA);
|
|
|
|
//----- Allocate per-control memory -----
|
|
if (NULL == ppcd) {
|
|
ppcd = (LPPERCONTROLDATA)CoTaskMemAlloc(sizeof(PERCONTROLDATA));
|
|
if (NULL == ppcd)
|
|
return NULL;
|
|
ZeroMemory(ppcd, sizeof(PERCONTROLDATA));
|
|
|
|
SetWindowLongPtr(htv, GWLP_USERDATA, (LONG_PTR)ppcd);
|
|
}
|
|
|
|
pfl = !fQL ? &ppcd->flFavorites : &ppcd->flQuickLinks;
|
|
if (NULL == pfl->pfs) {
|
|
pfl->pfs = (LPFAVSTRUC)CoTaskMemAlloc(sizeof(FAVSTRUC) * SFav::GetMaxNumber(fQL));
|
|
if (NULL == pfl->pfs)
|
|
return NULL;
|
|
ZeroMemory(pfl->pfs, sizeof(FAVSTRUC) * SFav::GetMaxNumber(fQL));
|
|
}
|
|
|
|
return pfl->pfs;
|
|
}
|
|
|
|
SFav* SFav::GetNext(HWND htv, BOOL fQL /*= FALSE*/) const
|
|
{
|
|
SFav* pfsFirst;
|
|
UINT nCur;
|
|
|
|
pfsFirst = GetFirst(htv, fQL);
|
|
if (pfsFirst == NULL)
|
|
return NULL;
|
|
|
|
for (nCur = (UINT)(this - pfsFirst + 1); nCur < GetMaxNumber(fQL); nCur++)
|
|
if ((pfsFirst + nCur)->wType != FTYPE_UNUSED)
|
|
break;
|
|
|
|
return (nCur < GetMaxNumber(fQL) ? (pfsFirst + nCur) : NULL);
|
|
}
|
|
|
|
void SFav::Free(HWND htv, BOOL fQL, LPCTSTR pszExtractPath /*= NULL*/)
|
|
{
|
|
if (pszIconFile != NULL && pszExtractPath != NULL)
|
|
if (PathIsPrefix(pszExtractPath, pszIconFile)) {
|
|
SetFileAttributes(pszIconFile, FILE_ATTRIBUTE_NORMAL);
|
|
DeleteFile(pszIconFile);
|
|
}
|
|
|
|
if (htv != NULL && pTvItem != NULL && pTvItem->hItem != NULL)
|
|
TreeView_DeleteItem(htv, pTvItem->hItem);
|
|
Delete();
|
|
|
|
//----- Decrement the number of items -----
|
|
LPPERCONTROLDATA ppcd;
|
|
LPFAVLIST pfl;
|
|
|
|
ppcd = (LPPERCONTROLDATA)GetWindowLongPtr(htv, GWLP_USERDATA);
|
|
ASSERT (NULL != ppcd);
|
|
|
|
pfl = !fQL ? &ppcd->flFavorites : &ppcd->flQuickLinks;
|
|
ASSERT(pfl->cElements > 0);
|
|
pfl->cElements--;
|
|
|
|
//----- Free per-control memory -----
|
|
if (0 == pfl->cElements) {
|
|
CoTaskMemFree(pfl->pfs);
|
|
|
|
// switch to the other one
|
|
pfl = fQL ? &ppcd->flFavorites : &ppcd->flQuickLinks;
|
|
if (0 == pfl->cElements) {
|
|
CoTaskMemFree(ppcd);
|
|
SetWindowLongPtr(htv, GWLP_USERDATA, NULL);
|
|
}
|
|
}
|
|
}
|
|
|
|
UINT SFav::GetNumber(HWND htv, BOOL fQL /*= FALSE*/)
|
|
{
|
|
LPPERCONTROLDATA ppcd;
|
|
|
|
ppcd = (LPPERCONTROLDATA)GetWindowLongPtr(htv, GWLP_USERDATA);
|
|
if (NULL == ppcd)
|
|
return 0;
|
|
|
|
return (!fQL ? ppcd->flFavorites.cElements : ppcd->flQuickLinks.cElements);
|
|
}
|
|
|
|
UINT SFav::GetMaxNumber(BOOL fQL /*= FALSE*/)
|
|
{
|
|
return (!fQL ? NUM_FAVS : NUM_LINKS) + 1;
|
|
}
|
|
|
|
BOOL SFav::Expand(WORD wFlags /*= FF_DEFAULT*/)
|
|
{
|
|
BOOL fZeroInit;
|
|
|
|
if (wFlags == FF_DEFAULT) {
|
|
if (wType != FTYPE_URL && wType != FTYPE_FOLDER)
|
|
goto Fail;
|
|
|
|
wFlags = (wType == FTYPE_URL) ? (WORD)(FF_NAME | FF_URL | FF_ICON) : (WORD)FF_NAME;
|
|
wFlags |= FF_TVI;
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_NAME)) {
|
|
fZeroInit = (pszName == NULL || *pszName == TEXT('\0'));
|
|
|
|
pszName = (LPTSTR)CoTaskMemRealloc(pszName, MAX_PATH*sizeof(TCHAR));
|
|
if (pszName == NULL)
|
|
goto Fail;
|
|
|
|
if (fZeroInit)
|
|
ZeroMemory(pszName, MAX_PATH);
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_PATH)) {
|
|
fZeroInit = (pszPath == NULL || *pszPath == TEXT('\0'));
|
|
|
|
pszPath = (LPTSTR)CoTaskMemRealloc(pszPath, MAX_PATH*sizeof(TCHAR));
|
|
if (pszPath == NULL)
|
|
goto Fail;
|
|
|
|
if (fZeroInit)
|
|
ZeroMemory(pszPath, MAX_PATH);
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_URL)) {
|
|
fZeroInit = (pszUrl == NULL || *pszUrl == TEXT('\0'));
|
|
|
|
pszUrl = (LPTSTR)CoTaskMemRealloc(pszUrl, INTERNET_MAX_URL_LENGTH*sizeof(TCHAR));
|
|
if (pszUrl == NULL)
|
|
goto Fail;
|
|
|
|
if (fZeroInit)
|
|
ZeroMemory(pszUrl, INTERNET_MAX_URL_LENGTH);
|
|
}
|
|
else
|
|
if (wType == FTYPE_FOLDER)
|
|
if (pszUrl != NULL) {
|
|
CoTaskMemFree(pszUrl);
|
|
pszUrl = NULL;
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_ICON)) {
|
|
fZeroInit = (pszIconFile == NULL || *pszIconFile == TEXT('\0'));
|
|
|
|
pszIconFile = (LPTSTR)CoTaskMemRealloc(pszIconFile, INTERNET_MAX_URL_LENGTH*sizeof(TCHAR));
|
|
if (pszIconFile == NULL)
|
|
goto Fail;
|
|
|
|
if (fZeroInit)
|
|
ZeroMemory(pszIconFile, INTERNET_MAX_URL_LENGTH);
|
|
}
|
|
else
|
|
if (wType == FTYPE_FOLDER)
|
|
if (pszIconFile != NULL) {
|
|
CoTaskMemFree(pszIconFile);
|
|
pszIconFile = NULL;
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_TVI)) {
|
|
UINT nTreeViewTextLen;
|
|
|
|
fZeroInit = TRUE;
|
|
if (pTvItem == NULL) {
|
|
pTvItem = (LPTV_ITEM)CoTaskMemAlloc(sizeof(TV_ITEM));
|
|
if (pTvItem == NULL)
|
|
goto Fail;
|
|
ZeroMemory(pTvItem, sizeof(TV_ITEM));
|
|
}
|
|
else
|
|
fZeroInit = (pTvItem->pszText == NULL || *pTvItem->pszText == TEXT('\0'));
|
|
|
|
nTreeViewTextLen = (UINT)((wType == FTYPE_URL) ? (MAX_PATH + 3 + INTERNET_MAX_URL_LENGTH) : MAX_PATH);
|
|
pTvItem->pszText = (LPTSTR)CoTaskMemRealloc(pTvItem->pszText, nTreeViewTextLen*sizeof(TCHAR));
|
|
if (pTvItem->pszText == NULL)
|
|
goto Fail;
|
|
|
|
if (fZeroInit)
|
|
ZeroMemory(pTvItem->pszText, nTreeViewTextLen);
|
|
}
|
|
|
|
return TRUE;
|
|
|
|
Fail:
|
|
Delete();
|
|
return FALSE;
|
|
}
|
|
|
|
void SFav::Shrink(WORD wFlags /*= FF_ALL*/)
|
|
{
|
|
UINT nLen;
|
|
|
|
if (HasFlag(wFlags, FF_NAME) && pszName != NULL) {
|
|
nLen = (*pszName != TEXT('\0')) ? (StrLen(pszName) + 1) : 0;
|
|
pszName = (LPTSTR)CoTaskMemRealloc(pszName, nLen * sizeof(TCHAR));
|
|
ASSERT(pszName != NULL); // should not be empty
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_PATH) && pszPath != NULL) {
|
|
nLen = (*pszPath != TEXT('\0')) ? (StrLen(pszPath) + 1) : 0;
|
|
pszPath = (LPTSTR)CoTaskMemRealloc(pszPath, nLen * sizeof(TCHAR));
|
|
ASSERT(pszPath == NULL); // not used
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_URL) && pszUrl != NULL) {
|
|
nLen = (*pszUrl != TEXT('\0')) ? (StrLen(pszUrl) + 1) : 0;
|
|
pszUrl = (LPTSTR)CoTaskMemRealloc(pszUrl, nLen * sizeof(TCHAR));
|
|
ASSERT((wType == FTYPE_FOLDER && pszUrl == NULL) || pszUrl != NULL);
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_ICON) && pszIconFile != NULL) {
|
|
nLen = (*pszIconFile != TEXT('\0')) ? (StrLen(pszIconFile) + 1) : 0;
|
|
pszIconFile = (LPTSTR)CoTaskMemRealloc(pszIconFile, nLen * sizeof(TCHAR));
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_TVI) && pTvItem != NULL && pTvItem->pszText != NULL) {
|
|
pTvItem->pszText = (LPTSTR)CoTaskMemRealloc(pTvItem->pszText,
|
|
(StrLen(pTvItem->pszText) + 1) * sizeof(TCHAR));
|
|
ASSERT(pTvItem->pszText != NULL);
|
|
}
|
|
}
|
|
|
|
void SFav::Delete(WORD wFlags /*= FF_ALL*/)
|
|
{
|
|
if (HasFlag(wFlags, FF_NAME) && pszName != NULL) {
|
|
CoTaskMemFree(pszName);
|
|
pszName = NULL;
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_PATH) && pszPath != NULL) {
|
|
CoTaskMemFree(pszPath);
|
|
pszPath = NULL;
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_URL) && pszUrl != NULL) {
|
|
CoTaskMemFree(pszUrl);
|
|
pszUrl = NULL;
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_ICON) && pszIconFile != NULL) {
|
|
CoTaskMemFree(pszIconFile);
|
|
pszIconFile = NULL;
|
|
}
|
|
|
|
if (HasFlag(wFlags, FF_TVI) && pTvItem != NULL) {
|
|
if (pTvItem->pszText != NULL) {
|
|
CoTaskMemFree(pTvItem->pszText);
|
|
pTvItem->pszText = NULL;
|
|
}
|
|
|
|
CoTaskMemFree(pTvItem);
|
|
pTvItem = NULL;
|
|
}
|
|
|
|
if (wFlags == FF_ALL)
|
|
wType = FTYPE_UNUSED;
|
|
}
|
|
|
|
BOOL SFav::GetPath(HWND htv, LPTSTR pszResult, UINT cchResult /*= 0*/) const
|
|
{
|
|
SFav *pfs;
|
|
HTREEITEM htiCur, htiNext;
|
|
TCHAR szPath[MAX_PATH],
|
|
szAux [MAX_PATH];
|
|
|
|
if (pTvItem == NULL || pTvItem->hItem == NULL)
|
|
return FALSE;
|
|
|
|
if (pszResult == NULL)
|
|
return FALSE;
|
|
*pszResult = TEXT('\0');
|
|
|
|
if (cchResult == 0)
|
|
cchResult = MAX_PATH;
|
|
|
|
szPath[0] = szAux[0] = TEXT('\0');
|
|
for (htiCur = TreeView_GetParent(htv, pTvItem->hItem), htiNext = TreeView_GetParent(htv, htiCur);
|
|
htiNext != NULL;
|
|
htiCur = htiNext, htiNext = TreeView_GetParent(htv, htiCur)) {
|
|
|
|
pfs = ::getItem(htv, htiCur);
|
|
if (pfs == NULL)
|
|
break;
|
|
|
|
ASSERT(pfs->wType == FTYPE_FOLDER);
|
|
PathCombine(szAux, pfs->pszName, szPath);
|
|
StrCpy(szPath, szAux);
|
|
}
|
|
if (htiNext != NULL)
|
|
return FALSE;
|
|
|
|
if (cchResult <= (UINT)StrLen(szPath))
|
|
return FALSE;
|
|
|
|
StrCpy(pszResult, szPath);
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Exported routines
|
|
|
|
BOOL WINAPI MigrateFavoritesA(LPCSTR pszIns)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return migrateFavoritesHelper(A2CT(pszIns));
|
|
}
|
|
|
|
BOOL WINAPI MigrateFavoritesW(LPCWSTR pcwszIns)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return migrateFavoritesHelper(W2CT(pcwszIns));
|
|
}
|
|
|
|
void WINAPI MigrateToOldFavoritesA(LPCSTR pszIns)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
migrateToOldFavoritesHelper(A2CT(pszIns));
|
|
}
|
|
|
|
void WINAPI MigrateToOldFavoritesW(LPCWSTR pcwszIns)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
migrateToOldFavoritesHelper(W2CT(pcwszIns));
|
|
}
|
|
|
|
int WINAPI ImportFavoritesA(HWND htv, LPCSTR pszDefInf, LPCSTR pszIns, LPCSTR pszFixPath,
|
|
LPCSTR pszNewPath, BOOL fIgnoreOffline)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return importFavoritesHelper(htv, A2CT(pszDefInf), A2CT(pszIns), A2CT(pszFixPath),
|
|
A2CT(pszNewPath), fIgnoreOffline);
|
|
}
|
|
|
|
int WINAPI ImportFavoritesW(HWND htv, LPCWSTR pcwszDefInf, LPCWSTR pcwszIns,
|
|
LPCWSTR pcwszFixPath, LPCWSTR pcwszNewPath, BOOL fIgnoreOffline)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return importFavoritesHelper(htv, W2CT(pcwszDefInf), W2CT(pcwszIns), W2CT(pcwszFixPath),
|
|
W2CT(pcwszNewPath), fIgnoreOffline);
|
|
}
|
|
|
|
int WINAPI ImportQuickLinksA(HWND htv, LPCSTR pszDefInf, LPCSTR pszIns, LPCSTR pszFixPath,
|
|
LPCSTR pszNewPath, BOOL fIgnoreOffline)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return importQuickLinksHelper(htv, A2CT(pszDefInf), A2CT(pszIns), A2CT(pszFixPath),
|
|
A2CT(pszNewPath), fIgnoreOffline);
|
|
}
|
|
|
|
int WINAPI ImportQuickLinksW(HWND htv, LPCWSTR pcwszDefInf, LPCWSTR pcwszIns,
|
|
LPCWSTR pcwszFixPath, LPCWSTR pcwszNewPath, BOOL fIgnoreOffline)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return importQuickLinksHelper(htv, W2CT(pcwszDefInf), W2CT(pcwszIns), W2CT(pcwszFixPath),
|
|
W2CT(pcwszNewPath), fIgnoreOffline);
|
|
}
|
|
|
|
BOOL WINAPI NewUrlA(HWND htv, LPCSTR pszExtractPath, DWORD dwPlatformID, DWORD dwMode)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return newUrlHelper(htv, A2CT(pszExtractPath), dwPlatformID, dwMode);
|
|
}
|
|
|
|
BOOL WINAPI NewUrlW(HWND htv, LPCWSTR pcwszExtractPath, DWORD dwPlatformID, DWORD dwMode)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return newUrlHelper(htv, W2CT(pcwszExtractPath), dwPlatformID, dwMode);
|
|
}
|
|
|
|
BOOL WINAPI NewFolder(HWND htv)
|
|
{
|
|
LPFAVSTRUC pfsNew;
|
|
AEFAVPARAMS aefp;
|
|
int iResult;
|
|
|
|
ASSERT(isFavoriteItem(htv, TreeView_GetSelection(htv)) == S_OK);
|
|
|
|
pfsNew = pfsNew->CreateNew(htv);
|
|
if (pfsNew == NULL)
|
|
goto Fail;
|
|
|
|
pfsNew->wType = FTYPE_FOLDER;
|
|
|
|
ZeroMemory(&aefp, sizeof(aefp));
|
|
aefp.pfs = pfsNew;
|
|
aefp.fQL = FALSE;
|
|
aefp.hwndErrorParent = GetParent(htv);
|
|
aefp.htv = htv;
|
|
aefp.hti = TreeView_GetSelection(htv);
|
|
aefp.pszExtractPath = NULL;
|
|
aefp.dwPlatformID = PLATFORM_WIN32;
|
|
aefp.dwMode = IEM_CORP;
|
|
|
|
iResult = (int) DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FAVPOPUP), GetParent(htv),
|
|
addEditFavoriteDlgProc, (LPARAM)&aefp);
|
|
if (iResult == IDCANCEL)
|
|
goto Fail;
|
|
|
|
pfsNew->Add(htv, NULL);
|
|
return TRUE;
|
|
|
|
Fail:
|
|
if (pfsNew != NULL)
|
|
pfsNew->Delete();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
BOOL WINAPI ModifyFavoriteA(HWND htv, HTREEITEM hti, LPCSTR pszExtractPath, LPCSTR pszPrevExtractPath,
|
|
DWORD dwPlatformID, DWORD dwMode)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return modifyFavoriteHelper(htv, hti, A2CT(pszExtractPath), A2CT(pszPrevExtractPath), dwPlatformID, dwMode);
|
|
}
|
|
|
|
BOOL WINAPI ModifyFavoriteW(HWND htv, HTREEITEM hti, LPCWSTR pcwszExtractPath, LPCWSTR pcwszPrevExtractPath,
|
|
DWORD dwPlatformID, DWORD dwMode)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return modifyFavoriteHelper(htv, hti, W2CT(pcwszExtractPath), W2CT(pcwszPrevExtractPath), dwPlatformID, dwMode);
|
|
}
|
|
|
|
BOOL WINAPI DeleteFavoriteA(HWND htv, HTREEITEM hti, LPCSTR pszExtractPath)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return deleteFavoriteHelper(htv, hti, A2CT(pszExtractPath));
|
|
}
|
|
|
|
BOOL WINAPI DeleteFavoriteW(HWND htv, HTREEITEM hti, LPCWSTR pcwszExtractPath)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return deleteFavoriteHelper(htv, hti, W2CT(pcwszExtractPath));
|
|
}
|
|
|
|
BOOL WINAPI MoveUpFavorite(HWND htv, HTREEITEM hti)
|
|
{
|
|
HTREEITEM htiBrother1, htiBrother2;
|
|
|
|
htiBrother1 = TreeView_GetPrevSibling(htv, hti);
|
|
if (htiBrother1 == NULL)
|
|
return FALSE;
|
|
|
|
htiBrother2 = TreeView_GetPrevSibling(htv, htiBrother1);
|
|
if (htiBrother2 == NULL)
|
|
htiBrother2 = TVI_FIRST;
|
|
|
|
if (!importPath(htv, hti, &htiBrother2))
|
|
return FALSE;
|
|
ASSERT(htiBrother2 != NULL);
|
|
|
|
TreeView_SelectItem(htv, htiBrother2);
|
|
TreeView_DeleteItem(htv, hti);
|
|
TreeView_EnsureVisible(htv, htiBrother2);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WINAPI MoveDownFavorite(HWND htv, HTREEITEM hti)
|
|
{
|
|
HTREEITEM htiBrother;
|
|
|
|
htiBrother = TreeView_GetNextSibling(htv, hti);
|
|
if (htiBrother == NULL)
|
|
return FALSE;
|
|
|
|
if (!importPath(htv, hti, &htiBrother))
|
|
return FALSE;
|
|
ASSERT(htiBrother != NULL);
|
|
|
|
TreeView_SelectItem(htv, htiBrother);
|
|
TreeView_DeleteItem(htv, hti);
|
|
TreeView_EnsureVisible(htv, htiBrother);
|
|
return TRUE;
|
|
}
|
|
|
|
BOOL WINAPI IsFavoriteItem(HWND htv, HTREEITEM hti)
|
|
{
|
|
return (isFavoriteItem(htv, hti) == S_OK);
|
|
}
|
|
|
|
UINT WINAPI GetFavoritesNumber(HWND htv, BOOL fQL /*= FALSE*/)
|
|
{
|
|
return SFav::GetNumber(htv, fQL);
|
|
}
|
|
|
|
UINT WINAPI GetFavoritesMaxNumber(BOOL fQL /*= FALSE*/)
|
|
{
|
|
return SFav::GetMaxNumber(fQL);
|
|
}
|
|
|
|
int WINAPI ImportFavoritesCmdA(HWND htv, LPCSTR pszExtractPath)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return importFavoritesCmdHelper(htv, A2CT(pszExtractPath));
|
|
}
|
|
|
|
int WINAPI ImportFavoritesCmdW(HWND htv, LPCWSTR pcwszExtractPath)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
return importFavoritesCmdHelper(htv, W2CT(pcwszExtractPath));
|
|
}
|
|
|
|
void WINAPI ExportFavoritesA(HWND htv, LPCSTR pszIns, LPCSTR pszExtractPath, BOOL fFixUpPath)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
exportFavoritesHelper(htv, A2CT(pszIns), A2CT(pszExtractPath), fFixUpPath);
|
|
}
|
|
|
|
void WINAPI ExportFavoritesW(HWND htv, LPCWSTR pcwszIns, LPCWSTR pcwszExtractPath, BOOL fFixUpPath)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
exportFavoritesHelper(htv, W2CT(pcwszIns), W2CT(pcwszExtractPath), fFixUpPath);
|
|
}
|
|
|
|
void WINAPI ExportQuickLinksA(HWND htv, LPCSTR pszIns, LPCSTR pszExtractPath, BOOL fFixUpPath)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
exportQuickLinksHelper(htv, A2CT(pszIns), A2CT(pszExtractPath), fFixUpPath);
|
|
}
|
|
|
|
void WINAPI ExportQuickLinksW(HWND htv, LPCWSTR pcwszIns, LPCWSTR pcwszExtractPath, BOOL fFixUpPath)
|
|
{
|
|
USES_CONVERSION;
|
|
|
|
exportQuickLinksHelper(htv, W2CT(pcwszIns), W2CT(pcwszExtractPath), fFixUpPath);
|
|
}
|
|
|
|
void WINAPI GetFavoritesInfoTipA(LPNMTVGETINFOTIPA pGetInfoTipA)
|
|
{
|
|
NMTVGETINFOTIP GetInfoTip;
|
|
|
|
ZeroMemory(&GetInfoTip, sizeof(GetInfoTip));
|
|
GetInfoTip.pszText = (LPTSTR)LocalAlloc(LPTR, pGetInfoTipA->cchTextMax * sizeof(TCHAR));
|
|
if (GetInfoTip.pszText != NULL)
|
|
{
|
|
getFavoritesInfoTipHelper(TVInfoTipA2T(pGetInfoTipA, &GetInfoTip));
|
|
TVInfoTipT2A(&GetInfoTip, pGetInfoTipA);
|
|
LocalFree(GetInfoTip.pszText);
|
|
}
|
|
}
|
|
|
|
void WINAPI GetFavoritesInfoTipW(LPNMTVGETINFOTIPW pGetInfoTipW)
|
|
{
|
|
NMTVGETINFOTIP GetInfoTip;
|
|
|
|
ZeroMemory(&GetInfoTip, sizeof(GetInfoTip));
|
|
GetInfoTip.pszText = (LPTSTR)LocalAlloc(LPTR, pGetInfoTipW->cchTextMax * sizeof(TCHAR));
|
|
if (GetInfoTip.pszText != NULL)
|
|
{
|
|
getFavoritesInfoTipHelper(TVInfoTipW2T(pGetInfoTipW, &GetInfoTip));
|
|
TVInfoTipT2W(&GetInfoTip, pGetInfoTipW);
|
|
LocalFree(GetInfoTip.pszText);
|
|
}
|
|
}
|
|
|
|
BOOL WINAPI GetFavoriteUrlA(HWND htv, HTREEITEM hti, LPSTR pszUrl, DWORD cchSize)
|
|
{
|
|
LPTSTR pszUrlBuf = (LPTSTR)LocalAlloc(LPTR, cchSize * sizeof(TCHAR));
|
|
BOOL fRet;
|
|
|
|
if (pszUrlBuf == NULL)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
fRet = getFavoriteUrlHelper(htv, hti, pszUrlBuf);
|
|
if (fRet)
|
|
T2Abux(pszUrlBuf, pszUrl);
|
|
|
|
LocalFree(pszUrlBuf);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
BOOL WINAPI GetFavoriteUrlW(HWND htv, HTREEITEM hti, LPWSTR pwszUrl, DWORD cchSize)
|
|
{
|
|
LPTSTR pszUrlBuf = (LPTSTR)LocalAlloc(LPTR, cchSize * sizeof(TCHAR));
|
|
BOOL fRet;
|
|
|
|
if (pszUrlBuf == NULL)
|
|
fRet = FALSE;
|
|
else
|
|
{
|
|
fRet = getFavoriteUrlHelper(htv, hti, pszUrlBuf);
|
|
if (fRet)
|
|
T2Wbux(pszUrlBuf, pwszUrl);
|
|
|
|
LocalFree(pszUrlBuf);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
void WINAPI ProcessFavSelChange(HWND hDlg, HWND hTv, LPNMTREEVIEW pnmtv)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
|
|
if (HasFlag(pnmtv->itemNew.state, TVIS_BOLD)) {
|
|
int rgids[] = { IDC_MODIFY, IDC_REMOVE, IDC_TESTFAVURL, IDC_FAVUP, IDC_FAVDOWN };
|
|
|
|
EnsureDialogFocus(hDlg, rgids, countof(rgids), IDC_ADDURL);
|
|
DisableDlgItems (hDlg, rgids, countof(rgids));
|
|
}
|
|
else {
|
|
EnableDlgItem(hDlg, IDC_MODIFY);
|
|
EnableDlgItem(hDlg, IDC_REMOVE);
|
|
|
|
pfs = (LPFAVSTRUC)pnmtv->itemNew.lParam;
|
|
if (pfs != NULL)
|
|
EnableDlgItem2(hDlg, IDC_TESTFAVURL, (pfs->wType == FTYPE_URL));
|
|
|
|
if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_FAVONTOP)) {
|
|
EnableDlgItem2(hDlg, IDC_FAVUP, (NULL != TreeView_GetPrevSibling(hTv, pnmtv->itemNew.hItem)));
|
|
EnableDlgItem2(hDlg, IDC_FAVDOWN, (NULL != TreeView_GetNextSibling(hTv, pnmtv->itemNew.hItem)));
|
|
}
|
|
}
|
|
|
|
EnableDlgItem2(hDlg, IDC_ADDFOLDER, IsFavoriteItem(hTv, pnmtv->itemNew.hItem));
|
|
}
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
// Implementation helper routines
|
|
|
|
static BOOL migrateFavoritesHelper(LPCTSTR pszIns)
|
|
{
|
|
TCHAR szTitle[MAX_PATH],
|
|
szUrl[INTERNET_MAX_URL_LENGTH],
|
|
szKey[32];
|
|
LPCTSTR pszTitle;
|
|
LPTSTR pszBuffer;
|
|
HANDLE hIns;
|
|
DWORD dwInsSize;
|
|
UINT i;
|
|
|
|
// figure out if there are any favorites at all
|
|
// NOTE: (andrewgu) szUrl serves as a mere buffer in the processing below.
|
|
wnsprintf(szKey, countof(szKey), IK_TITLE_FMT, 1);
|
|
if (InsIsKeyEmpty(IS_FAVORITESEX, szKey, pszIns)) {
|
|
if (InsIsSectionEmpty(IS_FAVORITES, pszIns))
|
|
return TRUE;
|
|
}
|
|
else
|
|
return TRUE;
|
|
|
|
WritePrivateProfileString(NULL, NULL, NULL, pszIns);
|
|
hIns = CreateFile(pszIns, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hIns == INVALID_HANDLE_VALUE)
|
|
return FALSE;
|
|
|
|
dwInsSize = GetFileSize(hIns, NULL);
|
|
ASSERT(dwInsSize != 0xFFFFFFFF);
|
|
CloseHandle(hIns);
|
|
|
|
pszBuffer = (LPTSTR)CoTaskMemAlloc(dwInsSize*sizeof(TCHAR));
|
|
if (pszBuffer == NULL)
|
|
return FALSE;
|
|
ZeroMemory(pszBuffer, dwInsSize);
|
|
|
|
GetPrivateProfileString(IS_FAVORITES, NULL, TEXT(""), pszBuffer, (UINT)dwInsSize, pszIns);
|
|
ASSERT(*pszBuffer != TEXT('\0'));
|
|
|
|
for (i = 1, pszTitle = pszBuffer; *pszTitle != TEXT('\0'); pszTitle += StrLen(pszTitle) + 1, i++) {
|
|
InsGetString(IS_FAVORITES, pszTitle, szUrl, countof(szUrl), pszIns);
|
|
|
|
wnsprintf(szKey, countof(szKey), IK_TITLE_FMT, i);
|
|
StrCpy(szTitle, pszTitle);
|
|
decodeFavName(szTitle, pszIns);
|
|
WritePrivateProfileString(IS_FAVORITESEX, szKey, szTitle, pszIns);
|
|
|
|
wnsprintf(szKey, countof(szKey), IK_URL_FMT, i);
|
|
WritePrivateProfileString(IS_FAVORITESEX, szKey, szUrl, pszIns);
|
|
}
|
|
|
|
CoTaskMemFree(pszBuffer);
|
|
return TRUE;
|
|
}
|
|
|
|
static void migrateToOldFavoritesHelper(LPCTSTR pszIns)
|
|
{
|
|
TCHAR szTitle[MAX_PATH],
|
|
szUrl[INTERNET_MAX_URL_LENGTH],
|
|
szKey[32];
|
|
|
|
WritePrivateProfileString(IS_FAVORITES, NULL, NULL, pszIns);
|
|
|
|
for (UINT i = 1; TRUE; i++) {
|
|
wnsprintf(szKey, countof(szKey), IK_TITLE_FMT, i);
|
|
InsGetString(IS_FAVORITESEX, szKey, szTitle, countof(szTitle), pszIns);
|
|
if (szTitle[0] == TEXT('\0'))
|
|
break;
|
|
|
|
wnsprintf(szKey, countof(szKey), IK_URL_FMT, i);
|
|
InsGetString(IS_FAVORITESEX, szKey, szUrl, countof(szUrl), pszIns);
|
|
|
|
encodeFavName(szTitle, pszIns);
|
|
WritePrivateProfileString(IS_FAVORITES, szTitle, szUrl, pszIns);
|
|
}
|
|
|
|
WritePrivateProfileString(NULL, NULL, NULL, pszIns);
|
|
}
|
|
|
|
static int importFavoritesHelper(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns,
|
|
LPCTSTR pszFixPath, LPCTSTR pszNewPath, BOOL fIgnoreOffline)
|
|
{
|
|
return importItems(htv, pszDefInf, pszIns, pszFixPath, pszNewPath, fIgnoreOffline);
|
|
}
|
|
|
|
static int importQuickLinksHelper(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns,
|
|
LPCTSTR pszFixPath, LPCTSTR pszNewPath, BOOL fIgnoreOffline)
|
|
{
|
|
return importItems(htv, pszDefInf, pszIns, pszFixPath, pszNewPath, fIgnoreOffline, TRUE);
|
|
}
|
|
|
|
static BOOL newUrlHelper(HWND htv, LPCTSTR pszExtractPath, DWORD dwPlatformID, DWORD dwMode)
|
|
{
|
|
LPFAVSTRUC pfsNew;
|
|
AEFAVPARAMS aefp;
|
|
HTREEITEM htiSel;
|
|
int iResult;
|
|
BOOL fQL;
|
|
|
|
htiSel = TreeView_GetSelection(htv);
|
|
fQL = (isFavoriteItem(htv, htiSel) != S_OK);
|
|
|
|
pfsNew = pfsNew->CreateNew(htv, fQL);
|
|
if (pfsNew == NULL)
|
|
goto Fail;
|
|
|
|
pfsNew->wType = FTYPE_URL;
|
|
|
|
ZeroMemory(&aefp, sizeof(aefp));
|
|
aefp.pfs = pfsNew;
|
|
aefp.fQL = fQL;
|
|
aefp.hwndErrorParent = GetParent(htv);
|
|
aefp.htv = htv;
|
|
aefp.hti = htiSel;
|
|
aefp.pszExtractPath = pszExtractPath;
|
|
aefp.dwPlatformID = dwPlatformID;
|
|
aefp.dwMode = dwMode;
|
|
|
|
iResult = (int) DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FAVPOPUP), GetParent(htv),
|
|
addEditFavoriteDlgProc, (LPARAM)&aefp);
|
|
|
|
if (iResult == IDCANCEL)
|
|
goto Fail;
|
|
|
|
pfsNew->Add(htv, htiSel);
|
|
return TRUE;
|
|
|
|
Fail:
|
|
if (pfsNew != NULL)
|
|
pfsNew->Delete();
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
static BOOL modifyFavoriteHelper(HWND htv, HTREEITEM hti, LPCTSTR pszExtractPath, LPCTSTR pszPrevExtractPath,
|
|
DWORD dwPlatformID, DWORD dwMode)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
AEFAVPARAMS aefp;
|
|
int iResult;
|
|
|
|
pfs = getItem(htv, hti);
|
|
if (pfs == NULL)
|
|
return FALSE;
|
|
|
|
ZeroMemory(&aefp, sizeof(aefp));
|
|
aefp.pfs = pfs;
|
|
aefp.fQL = FALSE;
|
|
aefp.hwndErrorParent = GetParent(htv);
|
|
aefp.htv = htv;
|
|
aefp.hti = TreeView_GetParent(htv, hti);
|
|
aefp.pszExtractPath = pszExtractPath;
|
|
aefp.pszPrevExtractPath = pszPrevExtractPath;
|
|
aefp.dwPlatformID = dwPlatformID;
|
|
aefp.dwMode = dwMode;
|
|
|
|
iResult = (int) DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FAVPOPUP), GetParent(htv),
|
|
addEditFavoriteDlgProc, (LPARAM)&aefp);
|
|
|
|
if (iResult == IDCANCEL)
|
|
return FALSE;
|
|
|
|
if (pfs->pTvItem != NULL) {
|
|
TreeView_SetItem(htv, pfs->pTvItem);
|
|
|
|
if (pfs->pTvItem->hItem != NULL)
|
|
TreeView_SelectItem(htv, pfs->pTvItem->hItem);
|
|
}
|
|
|
|
return TRUE;
|
|
}
|
|
|
|
static BOOL deleteFavoriteHelper(HWND htv, HTREEITEM hti, LPCTSTR pszExtractPath)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
HTREEITEM htiChild;
|
|
|
|
htiChild = TreeView_GetChild(htv, hti);
|
|
if (htiChild != NULL) {
|
|
HTREEITEM htiSibling;
|
|
|
|
while ((htiSibling = TreeView_GetNextSibling(htv, htiChild)) != NULL)
|
|
deleteFavoriteHelper(htv, htiSibling, pszExtractPath);
|
|
|
|
deleteFavoriteHelper(htv, htiChild, pszExtractPath);
|
|
}
|
|
|
|
pfs = getItem(htv, hti);
|
|
if (pfs == NULL)
|
|
return FALSE;
|
|
|
|
pfs->Free(htv, (isFavoriteItem(htv, hti) != S_OK), pszExtractPath);
|
|
return TRUE;
|
|
}
|
|
|
|
static int importFavoritesCmdHelper(HWND htv, LPCTSTR pszExtractPath)
|
|
{
|
|
LPFAVSTRUC pfsFolder;
|
|
TCHAR szFolder[MAX_PATH],
|
|
szTitle[MAX_PATH];
|
|
|
|
pfsFolder = getFolderItem(htv, TreeView_GetSelection(htv));
|
|
if (pfsFolder == NULL || pfsFolder->pTvItem == NULL || pfsFolder->pTvItem->hItem == NULL)
|
|
return 0;
|
|
|
|
LoadString(g_hInst, IDS_BROWSEIMPORT, szTitle, countof(szTitle));
|
|
if (!BrowseForFolder(htv, szFolder, szTitle))
|
|
return 0;
|
|
|
|
if (szFolder[0] == TEXT('\0'))
|
|
return 0;
|
|
|
|
importPath (htv, pfsFolder->pTvItem->hItem, szFolder, pszExtractPath);
|
|
TreeView_Expand(htv, pfsFolder->pTvItem->hItem, TVE_EXPAND);
|
|
|
|
return pfsFolder->GetNumber(htv);
|
|
}
|
|
|
|
static void exportFavoritesHelper(HWND htv, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath /*= TRUE */)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
int i;
|
|
|
|
WritePrivateProfileString(IS_FAVORITESEX, NULL, NULL, pszIns);
|
|
|
|
pfs = pfs->GetFirst(htv);
|
|
if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
return;
|
|
|
|
i = exportItems(htv, pfs->pTvItem->hItem, pszIns, pszExtractPath, fFixUpPath);
|
|
|
|
// if no favorites, write out a flag so we don't repopulate with default favorites next time around
|
|
InsWriteBool(IS_BRANDING, IK_NOFAVORITES, (i == 1), pszIns);
|
|
}
|
|
|
|
static void exportQuickLinksHelper(HWND htv, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath /*= TRUE */)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
int i;
|
|
|
|
pfs = pfs->GetFirst(htv, TRUE);
|
|
if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
return;
|
|
|
|
i = exportItems(htv, pfs->pTvItem->hItem, pszIns, pszExtractPath, fFixUpPath);
|
|
|
|
// if no links, write out a flag so we don't repopulate with default links next time around
|
|
InsWriteBool(IS_BRANDING, IK_NOLINKS, (i == 1), pszIns);
|
|
|
|
// clear out any stuff that might be left over
|
|
SFav favEmpty;
|
|
for (i = (i >= 0) ? i : 1; (UINT)i < pfs->GetMaxNumber(TRUE); i++)
|
|
favEmpty.Save(NULL, i, pszIns, NULL, TRUE, fFixUpPath);
|
|
}
|
|
|
|
static void getFavoritesInfoTipHelper(LPNMTVGETINFOTIP pGetInfoTip)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
static TCHAR s_szFormat[80],
|
|
s_szAbsent[30],
|
|
s_szOfflineOn[30], s_szOfflineOff[30],
|
|
s_szEllipsis[] = TEXT("...");
|
|
|
|
TCHAR szBuffer[2 * MAX_PATH],
|
|
rgszAux [4][30];
|
|
LPCTSTR rgpszAux[4];
|
|
|
|
|
|
if (s_szFormat[0] == TEXT('\0')) {
|
|
LoadString(g_hInst, IDS_FAVS_TOOLTIPFORMAT, s_szFormat, countof(s_szFormat));
|
|
LoadString(g_hInst, IDS_FAVS_ABSENT, s_szAbsent, countof(s_szAbsent));
|
|
LoadString(g_hInst, IDS_FAVS_OFFLINE, s_szOfflineOn, countof(s_szAbsent));
|
|
LoadString(g_hInst, IDS_FAVS_NOOFFLINE, s_szOfflineOff, countof(s_szOfflineOff));
|
|
}
|
|
|
|
ASSERT(pGetInfoTip != NULL);
|
|
|
|
pfs = (LPFAVSTRUC)pGetInfoTip->lParam;
|
|
if (pfs == NULL || pfs->wType != FTYPE_URL)
|
|
{
|
|
StrCpyN(pGetInfoTip->pszText, pfs != NULL ? pfs->pszName : TEXT(""), pGetInfoTip->cchTextMax);
|
|
return;
|
|
}
|
|
|
|
ASSERT(pfs->pszName != NULL && pfs->pszUrl != NULL);
|
|
rgpszAux[0] = pfs->pszName;
|
|
rgpszAux[1] = pfs->pszUrl;
|
|
rgpszAux[2] = pfs->pszIconFile;
|
|
rgpszAux[3] = pfs->fOffline ? s_szOfflineOn : s_szOfflineOff;
|
|
|
|
for (UINT i = 0; i < countof(rgszAux); i++)
|
|
{
|
|
if (rgpszAux[i] == NULL)
|
|
StrCpy(rgszAux[i], s_szAbsent);
|
|
else
|
|
{
|
|
if (StrLen(rgpszAux[i]) < countof(rgszAux[i]))
|
|
StrCpy(rgszAux[i], rgpszAux[i]);
|
|
else
|
|
{
|
|
StrCpyN(rgszAux[i], rgpszAux[i], countof(rgszAux[i]) - countof(s_szEllipsis) + 1);
|
|
StrCpy(&rgszAux[i][countof(rgszAux[i]) - countof(s_szEllipsis)], s_szEllipsis);
|
|
}
|
|
}
|
|
}
|
|
wnsprintf(szBuffer, countof(szBuffer), s_szFormat, rgszAux[0], rgszAux[1], rgszAux[2],
|
|
rgszAux[3]);
|
|
StrCpyN(pGetInfoTip->pszText, szBuffer, pGetInfoTip->cchTextMax);
|
|
}
|
|
|
|
static BOOL getFavoriteUrlHelper(HWND htv, HTREEITEM hti, LPTSTR pszUrl)
|
|
{
|
|
LPFAVSTRUC pfs = getItem(htv, hti);
|
|
BOOL fRet = FALSE;
|
|
|
|
if ((pfs != NULL) && (pfs->pszUrl != NULL))
|
|
{
|
|
fRet = TRUE;
|
|
StrCpy(pszUrl, pfs->pszUrl);
|
|
}
|
|
|
|
return fRet;
|
|
}
|
|
|
|
int importItems(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns, LPCTSTR pszFixPath, LPCTSTR pszNewPath,
|
|
BOOL fIgnoreOffline, BOOL fQL /*= FALSE */)
|
|
{
|
|
LPFAVSTRUC pfs, pfsCur;
|
|
TCHAR szKey[32];
|
|
UINT i;
|
|
|
|
pfs = pfs->GetFirst(htv, fQL);
|
|
if (pfs != NULL && pfs->pTvItem != NULL && pfs->pTvItem->hItem != NULL) {
|
|
DeleteFavorite(htv, pfs->pTvItem->hItem, pszNewPath);
|
|
ASSERT(pfs->GetNumber(htv, fQL) == 0);
|
|
}
|
|
|
|
pfs = pfs->CreateNew(htv, fQL);
|
|
if (pfs == NULL)
|
|
return 0;
|
|
ASSERT(pfs == pfs->GetFirst(htv, fQL));
|
|
|
|
pfs->wType = FTYPE_FOLDER;
|
|
if (!pfs->Expand())
|
|
return 0;
|
|
|
|
LoadString(g_hInst, fQL ? IDS_LINKS : IDS_FAVFOLDER, pfs->pszName, MAX_PATH);
|
|
|
|
pfs->SetTVI();
|
|
pfs->pTvItem->stateMask = pfs->pTvItem->state = TVIS_BOLD;
|
|
pfs->Shrink();
|
|
|
|
TreeView_SelectItem(htv, NULL);
|
|
pfs->Add(htv, NULL);
|
|
ASSERT(pfs->pTvItem != NULL && pfs->pTvItem->hItem != NULL);
|
|
|
|
for (i = 1; TRUE; i++) {
|
|
pfsCur = pfs->CreateNew(htv, fQL);
|
|
if (pfsCur == NULL)
|
|
break;
|
|
|
|
if (pfsCur->Load(i, pszIns, fQL, pszFixPath, pszNewPath, fIgnoreOffline) != S_OK)
|
|
break;
|
|
|
|
pfsCur->Add(htv, pfs->pTvItem->hItem);
|
|
}
|
|
|
|
// NOTE: (andrewgu) this is an ugly special case when there are no quick links in the ins.
|
|
// it's a brief version of SFav::Load which only loads name and url fields. there are two
|
|
// alternative ways of doing this with SFav::Load. one is to special case the section to
|
|
// IS_STRINGS if extension of pszIns is *.inf, another is to make the section an in-parameter
|
|
// of SFav::Load.
|
|
if (i == 1 && !InsGetBool(IS_BRANDING, fQL ? IK_NOLINKS : IK_NOFAVORITES, FALSE, pszIns))
|
|
for (; TRUE; i++) {
|
|
pfsCur = pfsCur->CreateNew(htv, fQL);
|
|
if (pfsCur == NULL)
|
|
break;
|
|
|
|
pfsCur->wType = FTYPE_URL;
|
|
if (!pfsCur->Expand())
|
|
return pfs->GetNumber(htv, fQL);
|
|
|
|
*pfsCur->pszIconFile = TEXT('\0');
|
|
|
|
wnsprintf(szKey, countof(szKey), fQL ? IK_QUICKLINK_NAME : IK_TITLE_FMT, i);
|
|
InsGetSubstString(fQL ? IS_URL : IS_FAVORITESEX, szKey, pfsCur->pszName, MAX_PATH, pszDefInf);
|
|
if (*pfsCur->pszName == TEXT('\0')) {
|
|
pfsCur->Delete();
|
|
break;
|
|
}
|
|
StrCat(pfsCur->pszName, DOT_URL);
|
|
|
|
wnsprintf(szKey, countof(szKey), fQL ? IK_QUICKLINK_URL : IK_URL_FMT, i);
|
|
InsGetSubstString(fQL ? IS_URL : IS_FAVORITESEX, szKey, pfsCur->pszUrl, INTERNET_MAX_URL_LENGTH, pszDefInf);
|
|
ASSERT(*pfsCur->pszUrl != TEXT('\0'));
|
|
|
|
pfsCur->SetTVI();
|
|
pfsCur->Shrink();
|
|
pfsCur->Add(htv, pfs->pTvItem->hItem);
|
|
}
|
|
|
|
TreeView_Expand(htv, pfs->pTvItem->hItem, TVE_EXPAND);
|
|
return pfs->GetNumber(htv, fQL);
|
|
}
|
|
|
|
INT_PTR CALLBACK addEditFavoriteDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
LPAEFAVPARAMS paefp;
|
|
LPFAVSTRUC pfs;
|
|
TCHAR szName[MAX_PATH],
|
|
szIconFile[INTERNET_MAX_URL_LENGTH];
|
|
HWND hCtrl;
|
|
BOOL fResult,
|
|
fEnable, fWasEnabled;
|
|
|
|
fResult = FALSE;
|
|
switch (message) {
|
|
case WM_INITDIALOG:
|
|
paefp = (LPAEFAVPARAMS)lParam;
|
|
SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)paefp);
|
|
|
|
//----- Initialize contols -----
|
|
EnableDBCSChars(hDlg, IDE_FAVNAME);
|
|
EnableDBCSChars(hDlg, IDE_FAVURL);
|
|
EnableDBCSChars(hDlg, IDE_FAVICON);
|
|
|
|
Edit_LimitText(GetDlgItem(hDlg, IDE_FAVNAME), _MAX_FNAME);
|
|
Edit_LimitText(GetDlgItem(hDlg, IDE_FAVURL), INTERNET_MAX_URL_LENGTH-1);
|
|
Edit_LimitText(GetDlgItem(hDlg, IDE_FAVICON), _MAX_FNAME);
|
|
|
|
//----- Initialize SFav structure associated with this dialog -----
|
|
fResult = (paefp == NULL || (paefp->pfs != NULL ? !paefp->pfs->Expand() : TRUE));
|
|
if (fResult) {
|
|
EndDialog(hDlg, IDCANCEL);
|
|
break;
|
|
}
|
|
pfs = paefp->pfs;
|
|
|
|
//----- Initialize contols (Part II) -----
|
|
if (paefp->dwPlatformID != PLATFORM_WIN32) {
|
|
EnableWindow(GetDlgItem(hDlg, IDC_FAVICON), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDE_FAVICON), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_FAVICONBROWSE), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_AVAILOFFLINE), FALSE);
|
|
}
|
|
else
|
|
if (!HasFlag(paefp->dwMode, (IEM_CORP | IEM_PROFMGR)) && pfs->wType == FTYPE_URL)
|
|
EnableWindow(GetDlgItem(hDlg, IDC_AVAILOFFLINE), FALSE);
|
|
|
|
if (pfs->wType == FTYPE_FOLDER) {
|
|
EnableWindow(GetDlgItem(hDlg, IDC_FAVURL), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDE_FAVURL), FALSE);
|
|
|
|
if (paefp->dwPlatformID == PLATFORM_WIN32) {
|
|
EnableWindow(GetDlgItem(hDlg, IDC_FAVICON), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDE_FAVICON), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_FAVICONBROWSE), FALSE);
|
|
EnableWindow(GetDlgItem(hDlg, IDC_AVAILOFFLINE), FALSE);
|
|
}
|
|
else {
|
|
ASSERT(!IsWindowEnabled(GetDlgItem(hDlg, IDC_FAVICON)));
|
|
ASSERT(!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVICON)));
|
|
ASSERT(!IsWindowEnabled(GetDlgItem(hDlg, IDC_FAVICONBROWSE)));
|
|
ASSERT(!IsWindowEnabled(GetDlgItem(hDlg, IDC_AVAILOFFLINE)));
|
|
}
|
|
}
|
|
|
|
//----- Populate controls -----
|
|
if (pfs->pszName == NULL || *pfs->pszName == TEXT('\0')) {
|
|
UINT nID;
|
|
|
|
if (pfs->wType == FTYPE_URL)
|
|
nID = (!paefp->fQL ? IDS_NEW : IDS_NEWQL);
|
|
|
|
else {
|
|
ASSERT(pfs->wType == FTYPE_FOLDER);
|
|
nID = IDS_NEWFOLDER;
|
|
}
|
|
|
|
LoadString(g_hInst, nID, pfs->pszName, MAX_PATH);
|
|
}
|
|
SetDlgItemText(hDlg, IDE_FAVNAME, pfs->pszName);
|
|
|
|
if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVURL)))
|
|
;
|
|
else {
|
|
if (pfs->pszUrl == NULL || *pfs->pszUrl == TEXT('\0'))
|
|
StrCpy(pfs->pszUrl, TEXT("http://www."));
|
|
|
|
SetDlgItemText(hDlg, IDE_FAVURL, pfs->pszUrl);
|
|
}
|
|
|
|
if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVICON)))
|
|
;
|
|
else
|
|
if (pfs->pszIconFile != NULL && *pfs->pszIconFile != TEXT('\0'))
|
|
SetDlgItemText(hDlg, IDE_FAVICON, pfs->pszIconFile);
|
|
|
|
if (!IsWindowEnabled(GetDlgItem(hDlg, IDC_AVAILOFFLINE)))
|
|
;
|
|
else
|
|
if (pfs->fOffline)
|
|
CheckDlgButton(hDlg, IDC_AVAILOFFLINE, BST_CHECKED);
|
|
|
|
fResult = TRUE;
|
|
break;
|
|
|
|
case WM_COMMAND:
|
|
switch (LOWORD(wParam)) {
|
|
case IDE_FAVNAME:
|
|
case IDE_FAVURL:
|
|
case IDE_FAVICON:
|
|
switch (HIWORD(wParam)) {
|
|
case EN_CHANGE:
|
|
paefp = (LPAEFAVPARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
hCtrl = GetDlgItem(hDlg, IDOK);
|
|
fWasEnabled = IsWindowEnabled(hCtrl);
|
|
|
|
fEnable = (GetWindowTextLength(GetDlgItem(hDlg, IDE_FAVNAME)) > 0);
|
|
if (paefp->pfs->wType == FTYPE_URL)
|
|
fEnable &= (GetWindowTextLength(GetDlgItem(hDlg, IDE_FAVURL)) > 0);
|
|
|
|
if (fEnable != fWasEnabled)
|
|
EnableWindow(hCtrl, fEnable);
|
|
|
|
fResult = TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case IDC_FAVICONBROWSE:
|
|
GetDlgItemText(hDlg, IDE_FAVICON, szIconFile, countof(szIconFile));
|
|
|
|
if (!BrowseForFile(hDlg, szIconFile, countof(szIconFile), GFN_ICO))
|
|
break;
|
|
|
|
SetDlgItemText(hDlg, IDE_FAVICON, szIconFile);
|
|
fResult = TRUE;
|
|
break;
|
|
|
|
case IDOK:
|
|
paefp = (LPAEFAVPARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
if (!CheckField(hDlg, IDE_FAVNAME, FC_NONNULL | FC_PATH, PIVP_FILENAME_ONLY)) {
|
|
fResult = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVURL)))
|
|
;
|
|
else
|
|
if (!CheckField(hDlg, IDE_FAVURL, FC_NONNULL | FC_URL)) {
|
|
fResult = FALSE;
|
|
break;
|
|
}
|
|
|
|
if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVICON)))
|
|
;
|
|
else
|
|
if (!CheckField(hDlg, IDE_FAVICON, FC_URL | FC_FILE | FC_EXISTS)) {
|
|
fResult = FALSE;
|
|
break;
|
|
}
|
|
|
|
GetDlgItemText(hDlg, IDE_FAVNAME, szName, countof(szName));
|
|
StrRemoveWhitespace(szName);
|
|
pfs = findByName(paefp->htv, paefp->hti, szName);
|
|
if (pfs != NULL && pfs != paefp->pfs) {
|
|
HWND hCtrl;
|
|
|
|
ErrorMessageBox(paefp->hwndErrorParent, IDS_FAV_ERR_DUPLICATE);
|
|
hCtrl = GetDlgItem(hDlg, IDE_FAVNAME);
|
|
Edit_SetSel(hCtrl, 0, -1);
|
|
SetFocus(hCtrl);
|
|
|
|
fResult = FALSE;
|
|
break;
|
|
}
|
|
|
|
pfs = paefp->pfs; // reassign pfs back to paefp->pfs
|
|
ASSERT(pfs->pszName != NULL);
|
|
StrCpy(pfs->pszName, szName);
|
|
|
|
if (pfs->pszUrl != NULL)
|
|
if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVURL)))
|
|
*pfs->pszUrl = TEXT('\0');
|
|
|
|
else {
|
|
GetDlgItemText(hDlg, IDE_FAVURL, pfs->pszUrl, INTERNET_MAX_URL_LENGTH);
|
|
StrRemoveWhitespace(pfs->pszUrl);
|
|
}
|
|
|
|
if (pfs->pszIconFile != NULL)
|
|
if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVICON)))
|
|
*pfs->pszIconFile = TEXT('\0');
|
|
|
|
else {
|
|
GetDlgItemText(hDlg, IDE_FAVICON, szIconFile, countof(szIconFile));
|
|
StrRemoveWhitespace(szIconFile);
|
|
|
|
ASSERT(paefp->pszExtractPath != NULL);
|
|
|
|
if (*pfs->pszIconFile != TEXT('\0') && StrCmpI(szIconFile, pfs->pszIconFile) != 0)
|
|
{
|
|
if (PathIsPrefix(paefp->pszPrevExtractPath, pfs->pszIconFile))
|
|
DeleteFile(pfs->pszIconFile);
|
|
else
|
|
DeleteFileInDir(pfs->pszIconFile, paefp->pszExtractPath);
|
|
}
|
|
|
|
extractIcon(szIconFile, 1, paefp->pszExtractPath, pfs->pszIconFile, INTERNET_MAX_URL_LENGTH);
|
|
}
|
|
|
|
pfs->fOffline = IsWindowEnabled(GetDlgItem(hDlg, IDC_AVAILOFFLINE)) &&
|
|
(IsDlgButtonChecked(hDlg, IDC_AVAILOFFLINE) == BST_CHECKED);
|
|
|
|
pfs->SetTVI();
|
|
EndDialog(hDlg, IDOK);
|
|
fResult = TRUE;
|
|
break;
|
|
|
|
case IDCANCEL:
|
|
EndDialog(hDlg, IDCANCEL);
|
|
fResult = TRUE;
|
|
break;
|
|
}
|
|
break;
|
|
|
|
case WM_DESTROY:
|
|
paefp = (LPAEFAVPARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
|
|
|
|
if (paefp != NULL && paefp->pfs != NULL)
|
|
paefp->pfs->Shrink();
|
|
break;
|
|
}
|
|
|
|
return fResult;
|
|
}
|
|
|
|
|
|
LPFAVSTRUC getItem(HWND htv, HTREEITEM hti)
|
|
{
|
|
LPFAVSTRUC pfsResult;
|
|
TV_ITEM tvi;
|
|
|
|
if (htv == NULL || hti == NULL)
|
|
return NULL;
|
|
|
|
ZeroMemory(&tvi, sizeof(tvi));
|
|
tvi.mask = TVIF_PARAM;
|
|
tvi.hItem = hti;
|
|
TreeView_GetItem(htv, &tvi);
|
|
|
|
pfsResult = (LPFAVSTRUC)tvi.lParam;
|
|
if (pfsResult == NULL || pfsResult->pTvItem == NULL || pfsResult->pTvItem->hItem == NULL)
|
|
return NULL;
|
|
ASSERT(pfsResult->pTvItem->hItem == hti);
|
|
|
|
return pfsResult;
|
|
}
|
|
|
|
LPFAVSTRUC getFolderItem(HWND htv, HTREEITEM hti)
|
|
{
|
|
LPFAVSTRUC pfsResult;
|
|
|
|
if (htv == NULL || hti == NULL)
|
|
return NULL;
|
|
|
|
pfsResult = getItem(htv, hti);
|
|
if (pfsResult == NULL)
|
|
return NULL;
|
|
|
|
if (pfsResult->wType != FTYPE_FOLDER) {
|
|
pfsResult = getItem(htv, TreeView_GetParent(htv, hti));
|
|
if (pfsResult == NULL)
|
|
return NULL;
|
|
}
|
|
ASSERT(pfsResult->wType == FTYPE_FOLDER);
|
|
|
|
return pfsResult;
|
|
}
|
|
|
|
LPFAVSTRUC findByName(HWND htv, HTREEITEM hti, LPCTSTR pszName)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
HTREEITEM htiCur;
|
|
TCHAR szFolders[MAX_PATH];
|
|
LPTSTR pszFile;
|
|
|
|
if (pszName == NULL)
|
|
return NULL;
|
|
|
|
StrCpy(szFolders, pszName);
|
|
pszFile = PathFindFileName(szFolders);
|
|
|
|
if (pszFile == szFolders)
|
|
pfs = getFolderItem(htv, hti);
|
|
|
|
else {
|
|
*(pszFile-1) = TEXT('\0');
|
|
pszName = pszFile;
|
|
|
|
pfs = findPath(htv, hti, szFolders);
|
|
}
|
|
|
|
if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
return NULL;
|
|
|
|
for (htiCur = TreeView_GetChild(htv, pfs->pTvItem->hItem);
|
|
htiCur != NULL;
|
|
htiCur = TreeView_GetNextSibling(htv, htiCur)) {
|
|
|
|
pfs = getItem(htv, htiCur);
|
|
if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
return NULL;
|
|
|
|
if (StrCmpI(pfs->pszName, pszName) == 0)
|
|
break;
|
|
}
|
|
|
|
return (htiCur != NULL ? pfs : NULL);
|
|
}
|
|
|
|
LPFAVSTRUC findPath(HWND htv, HTREEITEM hti, LPCTSTR pszFolders)
|
|
{
|
|
LPFAVSTRUC pfsFirst,
|
|
pfsCur;
|
|
HTREEITEM htiCur;
|
|
TCHAR szPathChunk[MAX_PATH];
|
|
LPCTSTR pszCur, pszNext;
|
|
|
|
pfsFirst = pfsFirst->GetFirst(htv);
|
|
if (pfsFirst == NULL)
|
|
return NULL;
|
|
|
|
if (hti != NULL) {
|
|
pfsCur = getFolderItem(htv, hti);
|
|
if (pfsCur == NULL)
|
|
return NULL;
|
|
}
|
|
else
|
|
pfsCur = pfsFirst;
|
|
|
|
if (pfsCur->pTvItem == NULL || pfsCur->pTvItem->hItem == NULL)
|
|
return NULL;
|
|
|
|
if (pszFolders == NULL)
|
|
return pfsCur;
|
|
|
|
htiCur = pfsCur->pTvItem->hItem;
|
|
for (pszCur = pszFolders, pszNext = PathFindNextComponent(pszCur);
|
|
pszNext != NULL;
|
|
pszCur = pszNext, pszNext = PathFindNextComponent(pszCur)) {
|
|
|
|
ASSERT(pszNext-1 > pszCur);
|
|
StrCpyN(szPathChunk, pszCur, (int)(pszNext-pszCur) + (*pszNext != TEXT('\0') ? 0 : 1));
|
|
|
|
// determine if there is an object already for this path chunk
|
|
pfsCur = findByName(htv, htiCur, szPathChunk);
|
|
if (pfsCur == NULL ||
|
|
pfsCur->wType != FTYPE_FOLDER ||
|
|
pfsCur->pTvItem == NULL || pfsCur->pTvItem->hItem == NULL)
|
|
return NULL;
|
|
}
|
|
|
|
return (pszNext == NULL ? pfsCur : NULL);
|
|
}
|
|
|
|
HRESULT isFavoriteItem(HWND htv, HTREEITEM hti)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
HTREEITEM htiCur, htiNext;
|
|
|
|
if (htv == NULL || hti == NULL)
|
|
return E_INVALIDARG;
|
|
|
|
for (htiCur = TreeView_GetParent(htv, hti), htiNext = TreeView_GetParent(htv, htiCur);
|
|
htiNext != NULL;
|
|
htiCur = htiNext, htiNext = TreeView_GetParent(htv, htiCur))
|
|
;
|
|
|
|
if (htiCur == NULL)
|
|
htiCur = hti;
|
|
|
|
pfs = getItem(htv, htiCur);
|
|
if (pfs == NULL)
|
|
return E_FAIL;
|
|
|
|
return (pfs == pfs->GetFirst(htv) ? S_OK : S_FALSE);
|
|
}
|
|
|
|
LPFAVSTRUC createFolderItems(HWND htv, HTREEITEM hti, LPCTSTR pszFolders)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
HTREEITEM htiCur;
|
|
TCHAR szPathChunk[MAX_PATH];
|
|
LPCTSTR pszCur, pszNext;
|
|
|
|
if (pszFolders == NULL)
|
|
return NULL;
|
|
|
|
pfs = getFolderItem(htv, hti);
|
|
if (pfs == NULL)
|
|
return NULL;
|
|
|
|
if (pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
return NULL;
|
|
|
|
htiCur = pfs->pTvItem->hItem;
|
|
for (pszCur = pszFolders, pszNext = PathFindNextComponent(pszCur);
|
|
pszNext != NULL;
|
|
pszCur = pszNext, pszNext = PathFindNextComponent(pszCur)) {
|
|
|
|
ASSERT(pszNext-1 > pszCur);
|
|
StrCpyN(szPathChunk, pszCur, (int)(pszNext-pszCur) + (*pszNext != TEXT('\0') ? 0 : 1));
|
|
|
|
// determine if there is an object already for this path chunk
|
|
pfs = findByName(htv, htiCur, szPathChunk);
|
|
if (pfs != NULL) {
|
|
if (pfs->wType != FTYPE_FOLDER)
|
|
return NULL;
|
|
|
|
if (pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
return NULL;
|
|
|
|
htiCur = pfs->pTvItem->hItem;
|
|
continue;
|
|
}
|
|
|
|
// create this path chunk as SFav object
|
|
pfs = pfs->CreateNew(htv);
|
|
if (pfs == NULL)
|
|
return NULL;
|
|
|
|
pfs->wType = FTYPE_FOLDER;
|
|
if (!pfs->Expand())
|
|
return NULL;
|
|
|
|
StrCpy(pfs->pszName, szPathChunk);
|
|
pfs->SetTVI();
|
|
pfs->Shrink();
|
|
pfs->Add(htv, htiCur);
|
|
|
|
ASSERT(pfs->pTvItem != NULL && pfs->pTvItem->hItem != NULL);
|
|
htiCur = pfs->pTvItem->hItem;
|
|
}
|
|
|
|
return pfs;
|
|
}
|
|
|
|
BOOL importPath(HWND htv, HTREEITEM htiFrom, HTREEITEM *phtiAfter)
|
|
{
|
|
LPFAVSTRUC pfs;
|
|
TV_INSERTSTRUCT tvins;
|
|
TV_ITEM tvi;
|
|
HTREEITEM htiFromCur, htiToCur,
|
|
htiParent, htiChild,
|
|
*phtiQueueFrom, *phtiQueueTo;
|
|
HRESULT hr;
|
|
UINT nNumber,
|
|
nFromHead, nFromTail,
|
|
nToHead, nToTail;
|
|
BOOL fQL,
|
|
fResult;
|
|
|
|
if (phtiAfter == NULL || *phtiAfter == NULL)
|
|
return FALSE;
|
|
|
|
hr = isFavoriteItem(htv, htiFrom);
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
fQL = (hr != S_OK);
|
|
|
|
// REVIEW: (andrewgu) actually, if we are to support this at all there needs to be a better
|
|
// default.
|
|
pfs = pfs->GetFirst(htv, fQL);
|
|
if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
return FALSE;
|
|
|
|
if (htiFrom == NULL) {
|
|
htiFrom = pfs->pTvItem->hItem;
|
|
ASSERT(*phtiAfter != TVI_FIRST);
|
|
}
|
|
|
|
fResult = FALSE;
|
|
nNumber = pfs->GetNumber(htv, fQL);
|
|
nFromHead = nFromTail = 0;
|
|
nToHead = nToTail = 0;
|
|
|
|
// intialize queues
|
|
phtiQueueTo = NULL;
|
|
phtiQueueFrom = new HTREEITEM[nNumber];
|
|
if (phtiQueueFrom == NULL)
|
|
goto Exit;
|
|
ZeroMemory(phtiQueueFrom, sizeof(HTREEITEM) * nNumber);
|
|
|
|
phtiQueueTo = new HTREEITEM[nNumber];
|
|
if (phtiQueueTo == NULL)
|
|
goto Exit;
|
|
ZeroMemory(phtiQueueTo, sizeof(HTREEITEM) * nNumber);
|
|
|
|
// put first element into the From queue, migrate it over
|
|
*(phtiQueueFrom + nFromTail++) = htiFrom;
|
|
|
|
ZeroMemory(&tvi, sizeof(tvi));
|
|
tvi.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE;
|
|
tvi.hItem = htiFrom;
|
|
TreeView_GetItem(htv, &tvi);
|
|
|
|
pfs = (LPFAVSTRUC)tvi.lParam;
|
|
if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
goto Exit;
|
|
tvi.mask |= TVIF_TEXT;
|
|
tvi.hItem = NULL;
|
|
tvi.pszText = pfs->pTvItem->pszText;
|
|
tvi.cchTextMax = StrLen(pfs->pTvItem->pszText) + 1;
|
|
|
|
if (*phtiAfter == TVI_FIRST || *phtiAfter == TVI_LAST)
|
|
htiParent = TreeView_GetParent(htv, htiFrom);
|
|
else
|
|
htiParent = TreeView_GetParent(htv, *phtiAfter);
|
|
|
|
ZeroMemory(&tvins, sizeof(tvins));
|
|
tvins.hParent = htiParent;
|
|
tvins.hInsertAfter = *phtiAfter;
|
|
CopyMemory(&tvins.item, &tvi, sizeof(tvi));
|
|
pfs->pTvItem->hItem = TreeView_InsertItem(htv, &tvins);
|
|
|
|
pfs->pTvItem->mask = TVIF_HANDLE | TVIF_STATE;
|
|
TreeView_GetItem(htv, pfs->pTvItem);
|
|
|
|
ZeroMemory(&tvi, sizeof(tvi));
|
|
tvi.mask = TVIF_PARAM;
|
|
tvi.hItem = htiFrom;
|
|
tvi.lParam = NULL;
|
|
TreeView_SetItem(htv, &tvi);
|
|
|
|
*(phtiQueueTo + nToTail++) = pfs->pTvItem->hItem;
|
|
|
|
// breadth-first graph traversion, non-recursive version
|
|
while (nFromHead < nFromTail) {
|
|
htiFromCur = *(phtiQueueFrom + nFromHead++);
|
|
htiToCur = *(phtiQueueTo + nToHead++);
|
|
ASSERT(htiFromCur != NULL && htiToCur != NULL);
|
|
|
|
for (htiChild = TreeView_GetChild(htv, htiFromCur);
|
|
htiChild != NULL;
|
|
htiChild = TreeView_GetNextSibling(htv, htiChild)) {
|
|
|
|
*(phtiQueueFrom + nFromTail++) = htiChild;
|
|
ASSERT(nFromTail < nNumber);
|
|
|
|
ZeroMemory(&tvi, sizeof(tvi));
|
|
tvi.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE;
|
|
tvi.hItem = htiChild;
|
|
TreeView_GetItem(htv, &tvi);
|
|
|
|
pfs = (LPFAVSTRUC)tvi.lParam;
|
|
if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
goto Exit;
|
|
tvi.mask |= TVIF_TEXT;
|
|
tvi.hItem = NULL;
|
|
tvi.pszText = pfs->pTvItem->pszText;
|
|
tvi.cchTextMax = StrLen(pfs->pTvItem->pszText) + 1;
|
|
|
|
ZeroMemory(&tvins, sizeof(tvins));
|
|
tvins.hParent = htiToCur;
|
|
tvins.hInsertAfter = TVI_LAST;
|
|
CopyMemory(&tvins.item, &tvi, sizeof(tvi));
|
|
pfs->pTvItem->hItem = TreeView_InsertItem(htv, &tvins);
|
|
|
|
pfs->pTvItem->mask = TVIF_HANDLE | TVIF_STATE;
|
|
TreeView_GetItem(htv, pfs->pTvItem);
|
|
|
|
ZeroMemory(&tvi, sizeof(tvi));
|
|
tvi.mask = TVIF_PARAM;
|
|
tvi.hItem = htiChild;
|
|
tvi.lParam = NULL;
|
|
TreeView_SetItem(htv, &tvi);
|
|
|
|
*(phtiQueueTo + nToTail++) = pfs->pTvItem->hItem;
|
|
ASSERT(nToTail < nNumber);
|
|
}
|
|
}
|
|
|
|
ASSERT(nFromHead == nFromTail && nToHead == nFromHead && nToHead == nToTail);
|
|
fResult = TRUE;
|
|
|
|
// NOTE: (andrewgu) nFromHead is used is a mere counter here.
|
|
for (nFromHead = 0; nFromHead < nNumber; nFromHead++) {
|
|
if (*(phtiQueueFrom + nFromHead) == NULL)
|
|
break;
|
|
|
|
ZeroMemory(&tvi, sizeof(tvi));
|
|
tvi.mask = TVIF_STATE;
|
|
tvi.hItem = *(phtiQueueFrom + nFromHead);
|
|
TreeView_GetItem(htv, &tvi);
|
|
|
|
if (HasFlag(tvi.state, TVIS_EXPANDED))
|
|
TreeView_Expand(htv, *(phtiQueueTo + nFromHead), TVE_EXPAND);
|
|
}
|
|
|
|
Exit:
|
|
*phtiAfter = fResult ? *phtiQueueTo : NULL;
|
|
|
|
delete[] phtiQueueFrom;
|
|
delete[] phtiQueueTo;
|
|
|
|
return fResult;
|
|
}
|
|
|
|
void importPath(HWND htv, HTREEITEM hti, LPCTSTR pszFilesPath, LPCTSTR pszExtractPath, LPCTSTR pszReserved /*= NULL*/)
|
|
{
|
|
static LPCTSTR s_pszBasePath;
|
|
static BOOL s_fMaxReached;
|
|
|
|
ISubscriptionMgr2 *psm;
|
|
WIN32_FIND_DATA fd;
|
|
LPFAVSTRUC pfs;
|
|
TCHAR szPath[MAX_PATH],
|
|
szLinksPath[MAX_PATH];
|
|
HANDLE hFindFile;
|
|
HRESULT hr;
|
|
BOOL fQL,
|
|
fIgnoreOffline;
|
|
|
|
//----- Setup globals -----
|
|
if (NULL == pszReserved) {
|
|
s_pszBasePath = pszFilesPath;
|
|
s_fMaxReached = FALSE;
|
|
}
|
|
|
|
if (s_fMaxReached)
|
|
return;
|
|
|
|
if (NULL == pszFilesPath)
|
|
return;
|
|
|
|
hr = isFavoriteItem(htv, hti);
|
|
if (FAILED(hr))
|
|
return;
|
|
fQL = (S_OK != hr);
|
|
|
|
szLinksPath[0] = TEXT('\0');
|
|
if (!fQL)
|
|
getLinksPath(szLinksPath);
|
|
|
|
fIgnoreOffline = FALSE;
|
|
psm = NULL;
|
|
|
|
hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr2, (LPVOID *)&psm);
|
|
if (FAILED(hr))
|
|
fIgnoreOffline = TRUE;
|
|
|
|
PathCombine(szPath, pszFilesPath, TEXT("*.*"));
|
|
hFindFile = FindFirstFile(szPath, &fd);
|
|
if (INVALID_HANDLE_VALUE == hFindFile)
|
|
return;
|
|
|
|
do {
|
|
PathCombine(szPath, pszFilesPath, fd.cFileName);
|
|
|
|
if (HasFlag(fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) {
|
|
// skip "." and ".." sub-directories
|
|
if (0 == StrCmp(fd.cFileName, TEXT(".")) || 0 == StrCmp(fd.cFileName, TEXT("..")))
|
|
continue;
|
|
|
|
// skip folders if importing under quick links
|
|
if (fQL)
|
|
continue;
|
|
|
|
// magic trick for quick links
|
|
if (0 == StrCmpI(szPath, szLinksPath)) {
|
|
pfs = pfs->GetFirst(htv, TRUE);
|
|
if (NULL == pfs || NULL == pfs->pTvItem || NULL == pfs->pTvItem->hItem)
|
|
continue;
|
|
|
|
importPath(htv, pfs->pTvItem->hItem, szPath, pszExtractPath, szPath);
|
|
continue;
|
|
}
|
|
|
|
importPath(htv, hti, szPath, pszExtractPath, s_pszBasePath);
|
|
}
|
|
else { /* it's a file */
|
|
// skip all file with extensions other than *.url
|
|
if (!PathIsExtension(fd.cFileName, DOT_URL))
|
|
continue;
|
|
|
|
if (NULL == pszReserved)
|
|
pszReserved = pszFilesPath;
|
|
ASSERT(StrLen(pszReserved) <= StrLen(pszFilesPath));
|
|
|
|
// determine if there is an object already for this
|
|
pfs = findByName(htv, hti, &szPath[StrLen(pszReserved) + 1]);
|
|
if (NULL != pfs) {
|
|
if (FTYPE_URL != pfs->wType ||
|
|
NULL == pfs->pTvItem || NULL == pfs->pTvItem->hItem)
|
|
break;
|
|
|
|
pfs->Free(htv, fQL, pszExtractPath);
|
|
}
|
|
|
|
pfs = pfs->CreateNew(htv, fQL);
|
|
if (NULL == pfs) {
|
|
if (pfs->GetNumber(htv, fQL) == pfs->GetMaxNumber(fQL)) {
|
|
ErrorMessageBox(GetParent(htv), IDS_FAV_ERR_NOTALL);
|
|
s_fMaxReached = TRUE;
|
|
}
|
|
break;
|
|
}
|
|
|
|
hr = pfs->Load(&szPath[StrLen(pszReserved) + (PathHasBackslash(pszReserved) ? 0 : 1)], szPath, pszExtractPath, psm, fIgnoreOffline);
|
|
if (FAILED(hr))
|
|
break;
|
|
|
|
pfs->Add(htv, hti);
|
|
}
|
|
} while (!s_fMaxReached && FindNextFile(hFindFile, &fd));
|
|
FindClose(hFindFile);
|
|
}
|
|
|
|
int exportItems(HWND htv, HTREEITEM hti, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath /*= TRUE */)
|
|
{
|
|
struct SVisited {
|
|
HTREEITEM hti;
|
|
BOOL fVisited;
|
|
} *pVisited;
|
|
|
|
LPFAVSTRUC pfs;
|
|
HTREEITEM htiCur, htiChild,
|
|
*phtiStack;
|
|
HRESULT hr;
|
|
UINT i, j, nNumber,
|
|
nStack;
|
|
BOOL fQL;
|
|
|
|
if (pszIns == NULL)
|
|
return -1;
|
|
|
|
hr = isFavoriteItem(htv, hti);
|
|
if (FAILED(hr))
|
|
return -1;
|
|
fQL = (hr != S_OK);
|
|
|
|
pfs = getFolderItem(htv, hti);
|
|
if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
|
|
return -1;
|
|
|
|
nNumber = pfs->GetNumber(htv, fQL);
|
|
nStack = 0;
|
|
|
|
// intialize stack
|
|
phtiStack = new HTREEITEM[nNumber];
|
|
if (phtiStack == NULL)
|
|
return -1;
|
|
ZeroMemory(phtiStack, sizeof(HTREEITEM) * nNumber);
|
|
|
|
*phtiStack = pfs->pTvItem->hItem;
|
|
nStack++;
|
|
|
|
// initialize visited array
|
|
pVisited = new SVisited[nNumber];
|
|
if (pVisited == NULL)
|
|
{
|
|
delete [] phtiStack;
|
|
return -1;
|
|
}
|
|
for (i = 0; pfs != NULL; i++, pfs = pfs->GetNext(htv, fQL)) {
|
|
(pVisited + i)->hti = (pfs->pTvItem != NULL && pfs->pTvItem->hItem != NULL) ? pfs->pTvItem->hItem : NULL;
|
|
(pVisited + i)->fVisited = FALSE;
|
|
}
|
|
ASSERT(i == nNumber);
|
|
|
|
// mark root as visited
|
|
for (i = 0; i < nNumber; i++)
|
|
if ((pVisited + i)->hti == *phtiStack)
|
|
break;
|
|
ASSERT(i < nNumber);
|
|
(pVisited + i)->fVisited = TRUE;
|
|
|
|
for (j = 1; nStack > 0; ) {
|
|
htiCur = *(phtiStack + nStack-1);
|
|
|
|
// determine if there are non-visited children
|
|
for (htiChild = TreeView_GetChild(htv, htiCur);
|
|
htiChild != NULL;
|
|
htiChild = TreeView_GetNextSibling(htv, htiChild)) {
|
|
|
|
for (i = 0; i < nNumber; i++)
|
|
if ((pVisited + i)->hti == htiChild)
|
|
break;
|
|
if (i < nNumber && !(pVisited + i)->fVisited)
|
|
break;
|
|
}
|
|
|
|
if (htiChild != NULL) {
|
|
// add non-visited child to the stack
|
|
*(phtiStack + nStack) = htiChild;
|
|
nStack++;
|
|
|
|
ASSERT((pVisited + i)->hti == htiChild);
|
|
(pVisited + i)->fVisited = TRUE;
|
|
|
|
pfs = getItem(htv, htiChild);
|
|
if (pfs == NULL || pfs->wType != FTYPE_URL)
|
|
continue;
|
|
|
|
pfs->Save(htv, j++, pszIns, pszExtractPath, fQL, fFixUpPath);
|
|
}
|
|
else
|
|
// all visited -> pop
|
|
*(phtiStack + --nStack) = NULL;
|
|
}
|
|
|
|
delete[] phtiStack;
|
|
delete[] pVisited;
|
|
|
|
return j;
|
|
}
|
|
|
|
BOOL extractIcon(LPCTSTR pszIconFile, int iIconIndex, LPCTSTR pszExtractPath, LPTSTR pszResult, UINT cchResult)
|
|
{
|
|
TCHAR szExtractedFile[MAX_PATH];
|
|
HRESULT hr;
|
|
UINT i;
|
|
BOOL fURL;
|
|
|
|
if (pszIconFile == NULL || pszExtractPath == NULL || pszResult == NULL)
|
|
return FALSE;
|
|
*pszResult = TEXT('\0');
|
|
|
|
if (cchResult == 0)
|
|
cchResult = MAX_PATH;
|
|
|
|
fURL = PathIsURL(pszIconFile);
|
|
if (fURL) {
|
|
PathCombine(szExtractedFile, pszExtractPath, PathFindFileName(pszIconFile));
|
|
|
|
hr = URLDownloadToFile(NULL, pszIconFile, szExtractedFile, 0L, NULL);
|
|
if (FAILED(hr))
|
|
return FALSE;
|
|
}
|
|
else {
|
|
static LPCTSTR rgpszCopyExt[] = {
|
|
DOT_ICO,
|
|
DOT_URL
|
|
};
|
|
static LPCTSTR rgpszExtractExt[] = {
|
|
DOT_EXE,
|
|
DOT_DLL
|
|
};
|
|
|
|
IStream *pStm;
|
|
IPicture *pPic;
|
|
PICTDESC pd;
|
|
LPCTSTR pszExt;
|
|
LPVOID pIcon;
|
|
HANDLE hFile;
|
|
HGLOBAL hmem;
|
|
HICON hicon;
|
|
HRESULT hr;
|
|
DWORD dwWritten;
|
|
LONG cbIcon;
|
|
|
|
// if it's an icon file just copy it
|
|
pszExt = PathFindExtension(pszIconFile);
|
|
for (i = 0; i < countof(rgpszCopyExt); i++)
|
|
if (StrCmpI(pszExt, rgpszCopyExt[i]) == 0)
|
|
break;
|
|
if (i < countof(rgpszCopyExt)) {
|
|
StrCpy(szExtractedFile, pszIconFile);
|
|
goto Exit;
|
|
}
|
|
|
|
// if it doesn't have extension from which icon can be extracted bail out
|
|
for (i = 0; i < countof(rgpszExtractExt); i++)
|
|
if (StrCmpI(pszExt, rgpszExtractExt[i]) == 0)
|
|
break;
|
|
if (i >= countof(rgpszExtractExt))
|
|
return FALSE;
|
|
|
|
// extract icons
|
|
ExtractIconEx(pszIconFile, iIconIndex, &hicon, NULL, 1);
|
|
if (hicon == NULL)
|
|
return FALSE;
|
|
|
|
hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
|
|
if (FAILED(hr)) {
|
|
DestroyIcon(hicon);
|
|
return FALSE;
|
|
}
|
|
|
|
ZeroMemory(&pd, sizeof(pd));
|
|
pd.cbSizeofstruct = sizeof(pd);
|
|
pd.picType = PICTYPE_ICON;
|
|
pd.icon.hicon = hicon;
|
|
|
|
hr = OleCreatePictureIndirect(&pd, IID_IPicture, TRUE, (LPVOID *)&pPic);
|
|
if (FAILED(hr)) {
|
|
DestroyIcon(hicon);
|
|
return FALSE;
|
|
}
|
|
|
|
hr = pPic->SaveAsFile(pStm, TRUE, &cbIcon);
|
|
pPic->Release();
|
|
if (FAILED(hr)) {
|
|
pStm->Release();
|
|
return FALSE;
|
|
}
|
|
|
|
// generate a unique icon name
|
|
do {
|
|
GetTempFileName(pszExtractPath, PREFIX_ICON, 0, szExtractedFile);
|
|
DeleteFile(szExtractedFile);
|
|
PathRenameExtension(szExtractedFile, DOT_ICO);
|
|
} while (PathFileExists(szExtractedFile));
|
|
|
|
hFile = CreateFile(szExtractedFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
pStm->Release();
|
|
return FALSE;
|
|
}
|
|
|
|
GetHGlobalFromStream(pStm, &hmem);
|
|
ASSERT(hmem != NULL);
|
|
pIcon = GlobalLock(hmem);
|
|
ASSERT(pIcon != NULL);
|
|
|
|
WriteFile(hFile, pIcon, cbIcon, &dwWritten, NULL);
|
|
CloseHandle(hFile);
|
|
|
|
GlobalUnlock(hmem);
|
|
pStm->Release();
|
|
}
|
|
|
|
Exit:
|
|
if (cchResult <= (UINT)StrLen(szExtractedFile))
|
|
return FALSE;
|
|
|
|
StrCpy(pszResult, szExtractedFile);
|
|
return TRUE;
|
|
}
|
|
|
|
LPCTSTR getLinksPath(LPTSTR pszPath, UINT cchPath /*= 0*/)
|
|
{
|
|
LPITEMIDLIST pidl;
|
|
TCHAR szPath[MAX_PATH],
|
|
szLinks[MAX_PATH];
|
|
HRESULT hr;
|
|
|
|
if (pszPath != NULL)
|
|
*pszPath = TEXT('\0');
|
|
|
|
if (cchPath == 0)
|
|
cchPath = MAX_PATH;
|
|
|
|
hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
|
|
if (FAILED(hr))
|
|
return NULL;
|
|
|
|
hr = SHGetPathFromIDList(pidl, szPath) ? S_OK : E_FAIL;
|
|
CoTaskMemFree(pidl);
|
|
if (FAILED(hr))
|
|
return NULL;
|
|
ASSERT(szPath[0] != TEXT('\0'));
|
|
|
|
szLinks[0] = TEXT('\0');
|
|
LoadString(g_hInst, IDS_LINKS, szLinks, countof(szLinks));
|
|
if (szLinks[0] == TEXT('\0'))
|
|
return NULL;
|
|
|
|
PathAppend(szPath, szLinks);
|
|
if (cchPath <= (UINT)StrLen(szPath))
|
|
return NULL;
|
|
|
|
StrCpy(pszPath, szPath);
|
|
return pszPath;
|
|
}
|
|
|
|
LPTSTR encodeFavName(LPTSTR pszFavName, LPCTSTR pszIns)
|
|
{
|
|
TCHAR szWrk[MAX_PATH],
|
|
chWrk;
|
|
LPTSTR pszFrom;
|
|
LPTSTR pszTo;
|
|
BOOL fEncodeFavs;
|
|
|
|
StrCpy(szWrk, pszFavName);
|
|
pszFrom = szWrk;
|
|
pszTo = pszFavName;
|
|
fEncodeFavs = FALSE;
|
|
|
|
while (*pszFrom != TEXT('\0')) {
|
|
switch(chWrk = *pszFrom++) {
|
|
case TEXT('['):
|
|
fEncodeFavs = TRUE;
|
|
*pszTo++ = TEXT('%');
|
|
*pszTo++ = TEXT('(');
|
|
break;
|
|
|
|
case TEXT(']'):
|
|
fEncodeFavs = TRUE;
|
|
*pszTo++ = TEXT('%');
|
|
*pszTo++ = TEXT(')');
|
|
break;
|
|
|
|
case TEXT('='):
|
|
fEncodeFavs = TRUE;
|
|
*pszTo++ = TEXT('%');
|
|
*pszTo++ = TEXT('-');
|
|
break;
|
|
|
|
case TEXT('%'):
|
|
fEncodeFavs = TRUE;
|
|
*pszTo++ = TEXT('%');
|
|
*pszTo++ = TEXT('%');
|
|
break;
|
|
|
|
default:
|
|
*pszTo++ = chWrk;
|
|
break;
|
|
}
|
|
}
|
|
|
|
*pszTo = TEXT('\0');
|
|
|
|
InsWriteBool(IS_BRANDING, IK_FAVORITES_ENCODE, fEncodeFavs, pszIns);
|
|
return pszFavName;
|
|
}
|
|
|
|
LPTSTR decodeFavName(LPTSTR pszFavName, LPCTSTR pszIns)
|
|
{
|
|
TCHAR szWrk[MAX_PATH],
|
|
chWrk;
|
|
LPTSTR pszFrom;
|
|
LPTSTR pszTo;
|
|
|
|
if (!InsGetBool(IS_BRANDING, IK_FAVORITES_ENCODE, FALSE, pszIns))
|
|
return pszFavName;
|
|
|
|
StrCpy(szWrk, pszFavName);
|
|
pszFrom = szWrk;
|
|
pszTo = pszFavName;
|
|
while((*pszFrom != TEXT('\0')) && ((chWrk = *pszFrom++) != TEXT('\0'))) {
|
|
if (chWrk != TEXT('%'))
|
|
*pszTo++ = chWrk;
|
|
|
|
else {
|
|
switch(chWrk = *pszFrom++) {
|
|
case TEXT('('): *pszTo++ = TEXT('['); break;
|
|
case TEXT(')'): *pszTo++ = TEXT(']'); break;
|
|
case TEXT('-'): *pszTo++ = TEXT('='); break;
|
|
case TEXT('%'): *pszTo++ = TEXT('%'); break;
|
|
|
|
case TEXT('/'):
|
|
#ifndef _UNICODE
|
|
*pszTo++ = IsDBCSLeadByte(*(pszTo - 1)) ? TEXT('\\') : TEXT('/');
|
|
#else
|
|
*pszTo++ = TEXT('/');
|
|
#endif
|
|
break;
|
|
|
|
default:
|
|
*pszTo++ = TEXT('%');
|
|
*pszTo++ = chWrk;
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
*pszTo = TEXT('\0');
|
|
return pszFavName;
|
|
}
|