Leaked source code of windows server 2003
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

  1. #include "precomp.h"
  2. #include <olectl.h>
  3. // Implementation helper structures/routines declarations
  4. typedef struct tagFAVLIST {
  5. LPFAVSTRUC pfs;
  6. int cElements;
  7. } FAVLIST, (FAR *LPFAVLIST);
  8. typedef struct tagPERCONTROLDATA {
  9. FAVLIST flFavorites;
  10. FAVLIST flQuickLinks;
  11. } PERCONTROLDATA, (FAR *LPPERCONTROLDATA);
  12. typedef struct tagAEFAVPARAMS {
  13. LPFAVSTRUC pfs;
  14. BOOL fQL;
  15. HWND hwndErrorParent;
  16. HWND htv;
  17. HTREEITEM hti;
  18. LPCTSTR pszExtractPath;
  19. LPCTSTR pszPrevExtractPath;
  20. DWORD dwPlatformID;
  21. DWORD dwMode;
  22. } AEFAVPARAMS, (FAR *LPAEFAVPARAMS);
  23. static BOOL migrateFavoritesHelper(LPCTSTR pszIns);
  24. static void migrateToOldFavoritesHelper(LPCTSTR pszIns);
  25. static int importFavoritesHelper(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns,
  26. LPCTSTR pszFixPath, LPCTSTR pszNewPath, BOOL fIgnoreOffline);
  27. static int importQuickLinksHelper(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns,
  28. LPCTSTR pszFixPath, LPCTSTR pszNewPath, BOOL fIgnoreOffline);
  29. static BOOL newUrlHelper(HWND htv, LPCTSTR pszExtractPath, DWORD dwPlatformID, DWORD dwMode);
  30. static BOOL modifyFavoriteHelper(HWND htv, HTREEITEM hti, LPCTSTR pszExtractPath, LPCTSTR pszPrevExtractPath,
  31. DWORD dwPlatformID, DWORD dwMode);
  32. static BOOL deleteFavoriteHelper(HWND htv, HTREEITEM hti, LPCTSTR pszExtractPath);
  33. static int importFavoritesCmdHelper(HWND htv, LPCTSTR pszExtractPath);
  34. static void exportFavoritesHelper(HWND htv, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath = TRUE);
  35. static void exportQuickLinksHelper(HWND htv, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath = TRUE);
  36. static void getFavoritesInfoTipHelper(LPNMTVGETINFOTIP pGetInfoTip);
  37. static BOOL getFavoriteUrlHelper(HWND htv, HTREEITEM hti, LPTSTR pszUrl);
  38. static int importItems(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns, LPCTSTR pszFixPath, LPCTSTR pszNewPath,
  39. BOOL fIgnoreOffline, BOOL fQL = FALSE);
  40. static INT_PTR CALLBACK addEditFavoriteDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
  41. static LPFAVSTRUC getItem (HWND htv, HTREEITEM hti);
  42. static LPFAVSTRUC getFolderItem (HWND htv, HTREEITEM hti);
  43. static LPFAVSTRUC findByName (HWND htv, HTREEITEM hti, LPCTSTR pszName);
  44. static LPFAVSTRUC findPath (HWND htv, HTREEITEM hti, LPCTSTR pszFolders);
  45. static HRESULT isFavoriteItem(HWND htv, HTREEITEM hti);
  46. static LPFAVSTRUC createFolderItems(HWND htv, HTREEITEM hti, LPCTSTR pszFolders);
  47. static BOOL importPath (HWND htv, HTREEITEM htiFrom, HTREEITEM *phtiAfter);
  48. static void importPath (HWND htv, HTREEITEM hti, LPCTSTR pszFilesPath, LPCTSTR pszExtractPath, LPCTSTR pszReserved = NULL);
  49. static int exportItems(HWND htv, HTREEITEM hti, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath = TRUE);
  50. BOOL extractIcon(LPCTSTR pszIconFile, int iIconIndex, LPCTSTR pszExtractPath, LPTSTR pszResult, UINT cchResult);
  51. static LPCTSTR getLinksPath(LPTSTR pszPath, UINT cchPath = 0);
  52. static LPTSTR encodeFavName(LPTSTR pszFavName, LPCTSTR pszIns);
  53. static LPTSTR decodeFavName(LPTSTR pszFavName, LPCTSTR pszIns);
  54. /////////////////////////////////////////////////////////////////////////////
  55. // SFav constructors and destructors
  56. SFav::SFav()
  57. {
  58. wType = FTYPE_UNUSED;
  59. pszName = NULL;
  60. pszPath = NULL;
  61. pszUrl = NULL;
  62. pszIconFile = NULL;
  63. fOffline = FALSE;
  64. pTvItem = NULL;
  65. }
  66. SFav::~SFav()
  67. {
  68. Delete();
  69. }
  70. /////////////////////////////////////////////////////////////////////////////
  71. // SFav properties
  72. HRESULT SFav::Load(UINT nIndex, LPCTSTR pszIns, BOOL fQL /*= FALSE*/,
  73. LPCTSTR pszFixPath /*= NULL*/, LPCTSTR pszNewPath /*= NULL*/, BOOL fIgnoreOffline /*= FALSE*/)
  74. {
  75. TCHAR szKey[32];
  76. LPCTSTR pszSection, pszKeyFmt;
  77. if (pszIns == NULL)
  78. return E_INVALIDARG;
  79. if (!fQL) {
  80. pszSection = IS_FAVORITESEX;
  81. pszKeyFmt = IK_TITLE_FMT;
  82. }
  83. else {
  84. pszSection = IS_URL;
  85. pszKeyFmt = IK_QUICKLINK_NAME;
  86. }
  87. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  88. if (InsIsKeyEmpty(pszSection, szKey, pszIns))
  89. return S_FALSE;
  90. wType = FTYPE_URL;
  91. if (!Expand())
  92. return E_OUTOFMEMORY;
  93. // Title
  94. pszKeyFmt = (!fQL ? IK_TITLE_FMT : IK_QUICKLINK_NAME);
  95. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  96. InsGetString(pszSection, szKey, pszName, MAX_PATH, pszIns);
  97. if (*pszName == TEXT('\0'))
  98. goto Fail;
  99. // URL
  100. pszKeyFmt = (!fQL ? IK_URL_FMT : IK_QUICKLINK_URL);
  101. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  102. InsGetString(pszSection, szKey, pszUrl, INTERNET_MAX_URL_LENGTH, pszIns);
  103. if (*pszUrl == TEXT('\0'))
  104. goto Fail;
  105. // Icon file (never required)
  106. pszKeyFmt = (!fQL ? IK_ICON_FMT : IK_QUICKLINK_ICON);
  107. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  108. InsGetString(pszSection, szKey, pszIconFile, INTERNET_MAX_URL_LENGTH, pszIns);
  109. if (*pszIconFile != TEXT('\0') && !PathIsURL(pszIconFile)) {
  110. BOOL fTryToFix;
  111. fTryToFix = FALSE;
  112. if (pszFixPath == NULL)
  113. fTryToFix = TRUE;
  114. else
  115. if (PathIsPrefix(pszFixPath, pszIconFile))
  116. fTryToFix = !PathFileExists(pszIconFile);
  117. if (fTryToFix && pszNewPath != NULL) {
  118. TCHAR szNewPath[MAX_PATH];
  119. PathCombine(szNewPath, pszNewPath, PathFindFileName(pszIconFile));
  120. StrCpy(pszIconFile, szNewPath);
  121. if (!PathFileExists(pszIconFile))
  122. *pszIconFile = TEXT('\0');
  123. }
  124. }
  125. // Make available offline flag
  126. fOffline = FALSE;
  127. if (!fIgnoreOffline) {
  128. pszKeyFmt = (!fQL ? IK_OFFLINE_FMT : IK_QUICKLINK_OFFLINE);
  129. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  130. fOffline = InsGetBool(pszSection, szKey, FALSE, pszIns);
  131. }
  132. SetTVI();
  133. Shrink();
  134. return S_OK;
  135. Fail:
  136. Delete();
  137. return E_FAIL;
  138. }
  139. HRESULT SFav::Load(LPCTSTR pszName, LPCTSTR pszFavorite, LPCTSTR pszExtractPath,
  140. ISubscriptionMgr2 *psm /*= NULL*/, BOOL fIgnoreOffline /*= FALSE*/)
  141. {
  142. TCHAR szIconFile[INTERNET_MAX_URL_LENGTH];
  143. USES_CONVERSION;
  144. if (pszFavorite == NULL)
  145. return E_INVALIDARG;
  146. wType = FTYPE_URL;
  147. if (!Expand())
  148. return E_OUTOFMEMORY;
  149. // Title
  150. if (pszName == NULL)
  151. pszName = PathFindFileName(pszFavorite);
  152. else
  153. ASSERT(StrStrI(pszFavorite, pszName) != NULL);
  154. StrCpy(SFav::pszName, pszName);
  155. PathRenameExtension(SFav::pszName, DOT_URL);
  156. // URL
  157. InsGetString(IS_INTERNETSHORTCUT, IK_URL, pszUrl, INTERNET_MAX_URL_LENGTH, pszFavorite);
  158. if (*pszUrl == TEXT('\0'))
  159. goto Fail;
  160. // Icon file
  161. InsGetString(IS_INTERNETSHORTCUT, IK_ICONFILE, szIconFile, countof(szIconFile), pszFavorite);
  162. if (szIconFile[0] != TEXT('\0')) {
  163. int iIconIndex;
  164. iIconIndex = GetPrivateProfileInt(IS_INTERNETSHORTCUT, IK_ICONINDEX, 1, pszFavorite);
  165. ::extractIcon(szIconFile, iIconIndex, pszExtractPath, pszIconFile, INTERNET_MAX_URL_LENGTH);
  166. }
  167. // Make available offline flag
  168. fOffline = FALSE;
  169. if (!fIgnoreOffline) {
  170. HRESULT hr;
  171. BOOL fOwnSubMgr;
  172. fOwnSubMgr = FALSE;
  173. if (psm == NULL) {
  174. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr2, (LPVOID *)&psm);
  175. if (SUCCEEDED(hr))
  176. fOwnSubMgr = TRUE;
  177. }
  178. if (psm != NULL) {
  179. hr = psm->IsSubscribed(T2W(pszUrl), &fOffline);
  180. if (FAILED(hr))
  181. fOffline = FALSE;
  182. }
  183. if (fOwnSubMgr)
  184. psm->Release();
  185. }
  186. SetTVI();
  187. Shrink();
  188. return S_OK;
  189. Fail:
  190. Delete();
  191. return E_FAIL;
  192. }
  193. HRESULT SFav::Add(HWND htv, HTREEITEM hti)
  194. {
  195. SFav *pfsFolder;
  196. TV_INSERTSTRUCT tvins;
  197. HTREEITEM htiParent;
  198. if (hti == NULL)
  199. hti = TreeView_GetSelection(htv);
  200. pfsFolder = NULL;
  201. if (wType == FTYPE_URL) {
  202. TCHAR szFolders[MAX_PATH];
  203. LPTSTR pszFile;
  204. pszFile = PathFindFileName(pszName);
  205. if (pszFile > pszName) {
  206. *(pszFile-1) = TEXT('\0');
  207. StrCpy(szFolders, pszName);
  208. StrCpy(pszName, pszFile);
  209. pfsFolder = ::createFolderItems(htv, hti, szFolders);
  210. if (pfsFolder == NULL)
  211. goto Fail;
  212. }
  213. }
  214. SetTVI();
  215. if (pfsFolder == NULL)
  216. pfsFolder = ::getFolderItem(htv, hti);
  217. if (pfsFolder != NULL) {
  218. if (pfsFolder->pTvItem == NULL || pfsFolder->pTvItem->hItem == NULL)
  219. goto Fail;
  220. htiParent = pfsFolder->pTvItem->hItem;
  221. }
  222. else
  223. htiParent = TVI_ROOT;
  224. ZeroMemory(&tvins, sizeof(tvins));
  225. tvins.hParent = htiParent;
  226. tvins.hInsertAfter = TVI_LAST;
  227. CopyMemory(&tvins.item, pTvItem, sizeof(TV_ITEM));
  228. pTvItem->hItem = TreeView_InsertItem(htv, &tvins);
  229. pTvItem->mask = TVIF_HANDLE | TVIF_STATE;
  230. TreeView_GetItem(htv, pTvItem);
  231. if (pfsFolder != NULL)
  232. TreeView_Expand(htv, htiParent, TVE_EXPAND);
  233. TreeView_SelectItem(htv, pTvItem->hItem);
  234. //----- Increment the number of items -----
  235. LPPERCONTROLDATA ppcd;
  236. LPFAVLIST pfl;
  237. ppcd = (LPPERCONTROLDATA)GetWindowLongPtr(htv, GWLP_USERDATA);
  238. ASSERT (NULL != ppcd);
  239. pfl = (S_OK == ::isFavoriteItem(htv, pTvItem->hItem)) ? &ppcd->flFavorites : &ppcd->flQuickLinks;
  240. pfl->cElements++;
  241. return S_OK;
  242. Fail:
  243. Delete();
  244. return FALSE;
  245. }
  246. // NOTE: (andrewgu) can also be used to clear the entry in case of quick links
  247. HRESULT SFav::Save(HWND htv, UINT nIndex, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fQL /*= FALSE*/,
  248. BOOL fFixUpPath /*= TRUE*/)
  249. {
  250. TCHAR szAux[INTERNET_MAX_URL_LENGTH],
  251. szKey[32];
  252. LPCTSTR pszSection, pszKeyFmt,
  253. pszAux;
  254. if (pszIns == NULL)
  255. return E_INVALIDARG;
  256. // Name
  257. if (!fQL) {
  258. if (wType != FTYPE_URL)
  259. return E_UNEXPECTED;
  260. GetPath(htv, szAux);
  261. PathAppend(szAux, pszName);
  262. if (!PathIsExtension(szAux, DOT_URL))
  263. StrCat(szAux, DOT_URL);
  264. pszAux = szAux;
  265. ASSERT(*pszAux != TEXT('\0'));
  266. pszSection = IS_FAVORITESEX;
  267. pszKeyFmt = IK_TITLE_FMT;
  268. }
  269. else {
  270. if (pszName != NULL && wType != FTYPE_URL)
  271. return E_UNEXPECTED;
  272. pszAux = NULL;
  273. if (pszName != NULL) {
  274. StrCpy(szAux, pszName);
  275. if (!PathIsExtension(szAux, DOT_URL))
  276. StrCat(szAux, DOT_URL);
  277. pszAux = szAux;
  278. ASSERT(*pszAux != TEXT('\0'));
  279. }
  280. pszSection = IS_URL;
  281. pszKeyFmt = IK_QUICKLINK_NAME;
  282. }
  283. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  284. WritePrivateProfileString(pszSection, szKey, pszAux, pszIns);
  285. // URL
  286. if (!fQL) {
  287. ASSERT(pszUrl != NULL && *pszUrl != TEXT('\0'));
  288. pszKeyFmt = IK_URL_FMT;
  289. }
  290. else {
  291. if (pszName != NULL)
  292. { ASSERT(pszUrl != NULL && *pszUrl != TEXT('\0')); }
  293. else
  294. { ASSERT(pszUrl == NULL); }
  295. pszKeyFmt = IK_QUICKLINK_URL;
  296. }
  297. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  298. WritePrivateProfileString(pszSection, szKey, pszUrl, pszIns);
  299. // Icon file
  300. if (!fQL) {
  301. ASSERT(pszIconFile == NULL || *pszIconFile != TEXT('\0'));
  302. pszKeyFmt = IK_ICON_FMT;
  303. }
  304. else {
  305. if (pszName != NULL && pszIconFile != NULL)
  306. { ASSERT(*pszIconFile != TEXT('\0')); }
  307. else
  308. { ASSERT(pszIconFile == NULL); }
  309. pszKeyFmt = IK_QUICKLINK_ICON;
  310. }
  311. pszAux = NULL;
  312. if (pszIconFile != NULL) {
  313. ::extractIcon(pszIconFile, 1, pszExtractPath, szAux, countof(szAux));
  314. if (szAux[0] != TEXT('\0'))
  315. if (PathIsPrefix(pszExtractPath, szAux))
  316. pszAux = szAux;
  317. else {
  318. TCHAR szDest[MAX_PATH];
  319. ASSERT(PathFileExists(szAux));
  320. PathCombine(szDest, pszExtractPath, PathFindFileName(szAux));
  321. CopyFile(szAux, szDest, FALSE);
  322. SetFileAttributes(szDest, FILE_ATTRIBUTE_NORMAL);
  323. // (pritobla): fFixUpPath should be always TRUE if called by the IEAK
  324. // Wizard or the Profile Manager. The only case when it would
  325. // be FALSE is when called by OPKWIZ. They want to keep the path
  326. // to the icon files what the user entered because they don't use our
  327. // Wizard/ProfMgr logic of temp dirs.
  328. pszAux = fFixUpPath ? szDest : szAux;
  329. }
  330. }
  331. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  332. WritePrivateProfileString(pszSection, szKey, pszAux, pszIns);
  333. // Make available offline flag
  334. pszAux = NULL;
  335. pszKeyFmt = !fQL ? IK_OFFLINE_FMT : IK_QUICKLINK_OFFLINE;
  336. if (!fQL) {
  337. if (fOffline)
  338. pszAux = TEXT("1");
  339. }
  340. else
  341. if (pszName != NULL && fOffline)
  342. pszAux = TEXT("1");
  343. wnsprintf(szKey, countof(szKey), pszKeyFmt, nIndex);
  344. WritePrivateProfileString(pszSection, szKey, pszAux, pszIns);
  345. return S_OK;
  346. }
  347. void SFav::SetTVI()
  348. {
  349. if (!Expand(FF_TVI))
  350. return;
  351. if (wType == FTYPE_URL)
  352. wnsprintf(pTvItem->pszText, MAX_PATH + 3 + INTERNET_MAX_URL_LENGTH, TEXT("%s = %s"), pszName, pszUrl);
  353. else
  354. StrCpy(pTvItem->pszText, pszName);
  355. pTvItem->cchTextMax = StrLen(pTvItem->pszText) + 1;
  356. pTvItem->mask = TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE | TVIF_TEXT;
  357. pTvItem->lParam = (LPARAM)this;
  358. }
  359. /////////////////////////////////////////////////////////////////////////////
  360. // SFav operations
  361. SFav* SFav::CreateNew(HWND htv, BOOL fQL /*= FALSE*/)
  362. {
  363. SFav* pfsFirst;
  364. pfsFirst = GetFirst(htv, fQL);
  365. if (pfsFirst == NULL)
  366. return NULL;
  367. for (UINT i = 0; i < SFav::GetMaxNumber(fQL); i++)
  368. if ((pfsFirst + i)->wType == FTYPE_UNUSED)
  369. break;
  370. if (i >= SFav::GetMaxNumber(fQL))
  371. return NULL;
  372. return (pfsFirst + i);
  373. }
  374. SFav* SFav::GetFirst(HWND htv, BOOL fQL /*= FALSE*/)
  375. {
  376. LPPERCONTROLDATA ppcd;
  377. LPFAVLIST pfl;
  378. ppcd = (LPPERCONTROLDATA)GetWindowLongPtr(htv, GWLP_USERDATA);
  379. //----- Allocate per-control memory -----
  380. if (NULL == ppcd) {
  381. ppcd = (LPPERCONTROLDATA)CoTaskMemAlloc(sizeof(PERCONTROLDATA));
  382. if (NULL == ppcd)
  383. return NULL;
  384. ZeroMemory(ppcd, sizeof(PERCONTROLDATA));
  385. SetWindowLongPtr(htv, GWLP_USERDATA, (LONG_PTR)ppcd);
  386. }
  387. pfl = !fQL ? &ppcd->flFavorites : &ppcd->flQuickLinks;
  388. if (NULL == pfl->pfs) {
  389. pfl->pfs = (LPFAVSTRUC)CoTaskMemAlloc(sizeof(FAVSTRUC) * SFav::GetMaxNumber(fQL));
  390. if (NULL == pfl->pfs)
  391. return NULL;
  392. ZeroMemory(pfl->pfs, sizeof(FAVSTRUC) * SFav::GetMaxNumber(fQL));
  393. }
  394. return pfl->pfs;
  395. }
  396. SFav* SFav::GetNext(HWND htv, BOOL fQL /*= FALSE*/) const
  397. {
  398. SFav* pfsFirst;
  399. UINT nCur;
  400. pfsFirst = GetFirst(htv, fQL);
  401. if (pfsFirst == NULL)
  402. return NULL;
  403. for (nCur = (UINT)(this - pfsFirst + 1); nCur < GetMaxNumber(fQL); nCur++)
  404. if ((pfsFirst + nCur)->wType != FTYPE_UNUSED)
  405. break;
  406. return (nCur < GetMaxNumber(fQL) ? (pfsFirst + nCur) : NULL);
  407. }
  408. void SFav::Free(HWND htv, BOOL fQL, LPCTSTR pszExtractPath /*= NULL*/)
  409. {
  410. if (pszIconFile != NULL && pszExtractPath != NULL)
  411. if (PathIsPrefix(pszExtractPath, pszIconFile)) {
  412. SetFileAttributes(pszIconFile, FILE_ATTRIBUTE_NORMAL);
  413. DeleteFile(pszIconFile);
  414. }
  415. if (htv != NULL && pTvItem != NULL && pTvItem->hItem != NULL)
  416. TreeView_DeleteItem(htv, pTvItem->hItem);
  417. Delete();
  418. //----- Decrement the number of items -----
  419. LPPERCONTROLDATA ppcd;
  420. LPFAVLIST pfl;
  421. ppcd = (LPPERCONTROLDATA)GetWindowLongPtr(htv, GWLP_USERDATA);
  422. ASSERT (NULL != ppcd);
  423. pfl = !fQL ? &ppcd->flFavorites : &ppcd->flQuickLinks;
  424. ASSERT(pfl->cElements > 0);
  425. pfl->cElements--;
  426. //----- Free per-control memory -----
  427. if (0 == pfl->cElements) {
  428. CoTaskMemFree(pfl->pfs);
  429. // switch to the other one
  430. pfl = fQL ? &ppcd->flFavorites : &ppcd->flQuickLinks;
  431. if (0 == pfl->cElements) {
  432. CoTaskMemFree(ppcd);
  433. SetWindowLongPtr(htv, GWLP_USERDATA, NULL);
  434. }
  435. }
  436. }
  437. UINT SFav::GetNumber(HWND htv, BOOL fQL /*= FALSE*/)
  438. {
  439. LPPERCONTROLDATA ppcd;
  440. ppcd = (LPPERCONTROLDATA)GetWindowLongPtr(htv, GWLP_USERDATA);
  441. if (NULL == ppcd)
  442. return 0;
  443. return (!fQL ? ppcd->flFavorites.cElements : ppcd->flQuickLinks.cElements);
  444. }
  445. UINT SFav::GetMaxNumber(BOOL fQL /*= FALSE*/)
  446. {
  447. return (!fQL ? NUM_FAVS : NUM_LINKS) + 1;
  448. }
  449. BOOL SFav::Expand(WORD wFlags /*= FF_DEFAULT*/)
  450. {
  451. BOOL fZeroInit;
  452. if (wFlags == FF_DEFAULT) {
  453. if (wType != FTYPE_URL && wType != FTYPE_FOLDER)
  454. goto Fail;
  455. wFlags = (wType == FTYPE_URL) ? (WORD)(FF_NAME | FF_URL | FF_ICON) : (WORD)FF_NAME;
  456. wFlags |= FF_TVI;
  457. }
  458. if (HasFlag(wFlags, FF_NAME)) {
  459. fZeroInit = (pszName == NULL || *pszName == TEXT('\0'));
  460. pszName = (LPTSTR)CoTaskMemRealloc(pszName, MAX_PATH*sizeof(TCHAR));
  461. if (pszName == NULL)
  462. goto Fail;
  463. if (fZeroInit)
  464. ZeroMemory(pszName, MAX_PATH);
  465. }
  466. if (HasFlag(wFlags, FF_PATH)) {
  467. fZeroInit = (pszPath == NULL || *pszPath == TEXT('\0'));
  468. pszPath = (LPTSTR)CoTaskMemRealloc(pszPath, MAX_PATH*sizeof(TCHAR));
  469. if (pszPath == NULL)
  470. goto Fail;
  471. if (fZeroInit)
  472. ZeroMemory(pszPath, MAX_PATH);
  473. }
  474. if (HasFlag(wFlags, FF_URL)) {
  475. fZeroInit = (pszUrl == NULL || *pszUrl == TEXT('\0'));
  476. pszUrl = (LPTSTR)CoTaskMemRealloc(pszUrl, INTERNET_MAX_URL_LENGTH*sizeof(TCHAR));
  477. if (pszUrl == NULL)
  478. goto Fail;
  479. if (fZeroInit)
  480. ZeroMemory(pszUrl, INTERNET_MAX_URL_LENGTH);
  481. }
  482. else
  483. if (wType == FTYPE_FOLDER)
  484. if (pszUrl != NULL) {
  485. CoTaskMemFree(pszUrl);
  486. pszUrl = NULL;
  487. }
  488. if (HasFlag(wFlags, FF_ICON)) {
  489. fZeroInit = (pszIconFile == NULL || *pszIconFile == TEXT('\0'));
  490. pszIconFile = (LPTSTR)CoTaskMemRealloc(pszIconFile, INTERNET_MAX_URL_LENGTH*sizeof(TCHAR));
  491. if (pszIconFile == NULL)
  492. goto Fail;
  493. if (fZeroInit)
  494. ZeroMemory(pszIconFile, INTERNET_MAX_URL_LENGTH);
  495. }
  496. else
  497. if (wType == FTYPE_FOLDER)
  498. if (pszIconFile != NULL) {
  499. CoTaskMemFree(pszIconFile);
  500. pszIconFile = NULL;
  501. }
  502. if (HasFlag(wFlags, FF_TVI)) {
  503. UINT nTreeViewTextLen;
  504. fZeroInit = TRUE;
  505. if (pTvItem == NULL) {
  506. pTvItem = (LPTV_ITEM)CoTaskMemAlloc(sizeof(TV_ITEM));
  507. if (pTvItem == NULL)
  508. goto Fail;
  509. ZeroMemory(pTvItem, sizeof(TV_ITEM));
  510. }
  511. else
  512. fZeroInit = (pTvItem->pszText == NULL || *pTvItem->pszText == TEXT('\0'));
  513. nTreeViewTextLen = (UINT)((wType == FTYPE_URL) ? (MAX_PATH + 3 + INTERNET_MAX_URL_LENGTH) : MAX_PATH);
  514. pTvItem->pszText = (LPTSTR)CoTaskMemRealloc(pTvItem->pszText, nTreeViewTextLen*sizeof(TCHAR));
  515. if (pTvItem->pszText == NULL)
  516. goto Fail;
  517. if (fZeroInit)
  518. ZeroMemory(pTvItem->pszText, nTreeViewTextLen);
  519. }
  520. return TRUE;
  521. Fail:
  522. Delete();
  523. return FALSE;
  524. }
  525. void SFav::Shrink(WORD wFlags /*= FF_ALL*/)
  526. {
  527. UINT nLen;
  528. if (HasFlag(wFlags, FF_NAME) && pszName != NULL) {
  529. nLen = (*pszName != TEXT('\0')) ? (StrLen(pszName) + 1) : 0;
  530. pszName = (LPTSTR)CoTaskMemRealloc(pszName, nLen * sizeof(TCHAR));
  531. ASSERT(pszName != NULL); // should not be empty
  532. }
  533. if (HasFlag(wFlags, FF_PATH) && pszPath != NULL) {
  534. nLen = (*pszPath != TEXT('\0')) ? (StrLen(pszPath) + 1) : 0;
  535. pszPath = (LPTSTR)CoTaskMemRealloc(pszPath, nLen * sizeof(TCHAR));
  536. ASSERT(pszPath == NULL); // not used
  537. }
  538. if (HasFlag(wFlags, FF_URL) && pszUrl != NULL) {
  539. nLen = (*pszUrl != TEXT('\0')) ? (StrLen(pszUrl) + 1) : 0;
  540. pszUrl = (LPTSTR)CoTaskMemRealloc(pszUrl, nLen * sizeof(TCHAR));
  541. ASSERT((wType == FTYPE_FOLDER && pszUrl == NULL) || pszUrl != NULL);
  542. }
  543. if (HasFlag(wFlags, FF_ICON) && pszIconFile != NULL) {
  544. nLen = (*pszIconFile != TEXT('\0')) ? (StrLen(pszIconFile) + 1) : 0;
  545. pszIconFile = (LPTSTR)CoTaskMemRealloc(pszIconFile, nLen * sizeof(TCHAR));
  546. }
  547. if (HasFlag(wFlags, FF_TVI) && pTvItem != NULL && pTvItem->pszText != NULL) {
  548. pTvItem->pszText = (LPTSTR)CoTaskMemRealloc(pTvItem->pszText,
  549. (StrLen(pTvItem->pszText) + 1) * sizeof(TCHAR));
  550. ASSERT(pTvItem->pszText != NULL);
  551. }
  552. }
  553. void SFav::Delete(WORD wFlags /*= FF_ALL*/)
  554. {
  555. if (HasFlag(wFlags, FF_NAME) && pszName != NULL) {
  556. CoTaskMemFree(pszName);
  557. pszName = NULL;
  558. }
  559. if (HasFlag(wFlags, FF_PATH) && pszPath != NULL) {
  560. CoTaskMemFree(pszPath);
  561. pszPath = NULL;
  562. }
  563. if (HasFlag(wFlags, FF_URL) && pszUrl != NULL) {
  564. CoTaskMemFree(pszUrl);
  565. pszUrl = NULL;
  566. }
  567. if (HasFlag(wFlags, FF_ICON) && pszIconFile != NULL) {
  568. CoTaskMemFree(pszIconFile);
  569. pszIconFile = NULL;
  570. }
  571. if (HasFlag(wFlags, FF_TVI) && pTvItem != NULL) {
  572. if (pTvItem->pszText != NULL) {
  573. CoTaskMemFree(pTvItem->pszText);
  574. pTvItem->pszText = NULL;
  575. }
  576. CoTaskMemFree(pTvItem);
  577. pTvItem = NULL;
  578. }
  579. if (wFlags == FF_ALL)
  580. wType = FTYPE_UNUSED;
  581. }
  582. BOOL SFav::GetPath(HWND htv, LPTSTR pszResult, UINT cchResult /*= 0*/) const
  583. {
  584. SFav *pfs;
  585. HTREEITEM htiCur, htiNext;
  586. TCHAR szPath[MAX_PATH],
  587. szAux [MAX_PATH];
  588. if (pTvItem == NULL || pTvItem->hItem == NULL)
  589. return FALSE;
  590. if (pszResult == NULL)
  591. return FALSE;
  592. *pszResult = TEXT('\0');
  593. if (cchResult == 0)
  594. cchResult = MAX_PATH;
  595. szPath[0] = szAux[0] = TEXT('\0');
  596. for (htiCur = TreeView_GetParent(htv, pTvItem->hItem), htiNext = TreeView_GetParent(htv, htiCur);
  597. htiNext != NULL;
  598. htiCur = htiNext, htiNext = TreeView_GetParent(htv, htiCur)) {
  599. pfs = ::getItem(htv, htiCur);
  600. if (pfs == NULL)
  601. break;
  602. ASSERT(pfs->wType == FTYPE_FOLDER);
  603. PathCombine(szAux, pfs->pszName, szPath);
  604. StrCpy(szPath, szAux);
  605. }
  606. if (htiNext != NULL)
  607. return FALSE;
  608. if (cchResult <= (UINT)StrLen(szPath))
  609. return FALSE;
  610. StrCpy(pszResult, szPath);
  611. return TRUE;
  612. }
  613. /////////////////////////////////////////////////////////////////////////////
  614. // Exported routines
  615. BOOL WINAPI MigrateFavoritesA(LPCSTR pszIns)
  616. {
  617. USES_CONVERSION;
  618. return migrateFavoritesHelper(A2CT(pszIns));
  619. }
  620. BOOL WINAPI MigrateFavoritesW(LPCWSTR pcwszIns)
  621. {
  622. USES_CONVERSION;
  623. return migrateFavoritesHelper(W2CT(pcwszIns));
  624. }
  625. void WINAPI MigrateToOldFavoritesA(LPCSTR pszIns)
  626. {
  627. USES_CONVERSION;
  628. migrateToOldFavoritesHelper(A2CT(pszIns));
  629. }
  630. void WINAPI MigrateToOldFavoritesW(LPCWSTR pcwszIns)
  631. {
  632. USES_CONVERSION;
  633. migrateToOldFavoritesHelper(W2CT(pcwszIns));
  634. }
  635. int WINAPI ImportFavoritesA(HWND htv, LPCSTR pszDefInf, LPCSTR pszIns, LPCSTR pszFixPath,
  636. LPCSTR pszNewPath, BOOL fIgnoreOffline)
  637. {
  638. USES_CONVERSION;
  639. return importFavoritesHelper(htv, A2CT(pszDefInf), A2CT(pszIns), A2CT(pszFixPath),
  640. A2CT(pszNewPath), fIgnoreOffline);
  641. }
  642. int WINAPI ImportFavoritesW(HWND htv, LPCWSTR pcwszDefInf, LPCWSTR pcwszIns,
  643. LPCWSTR pcwszFixPath, LPCWSTR pcwszNewPath, BOOL fIgnoreOffline)
  644. {
  645. USES_CONVERSION;
  646. return importFavoritesHelper(htv, W2CT(pcwszDefInf), W2CT(pcwszIns), W2CT(pcwszFixPath),
  647. W2CT(pcwszNewPath), fIgnoreOffline);
  648. }
  649. int WINAPI ImportQuickLinksA(HWND htv, LPCSTR pszDefInf, LPCSTR pszIns, LPCSTR pszFixPath,
  650. LPCSTR pszNewPath, BOOL fIgnoreOffline)
  651. {
  652. USES_CONVERSION;
  653. return importQuickLinksHelper(htv, A2CT(pszDefInf), A2CT(pszIns), A2CT(pszFixPath),
  654. A2CT(pszNewPath), fIgnoreOffline);
  655. }
  656. int WINAPI ImportQuickLinksW(HWND htv, LPCWSTR pcwszDefInf, LPCWSTR pcwszIns,
  657. LPCWSTR pcwszFixPath, LPCWSTR pcwszNewPath, BOOL fIgnoreOffline)
  658. {
  659. USES_CONVERSION;
  660. return importQuickLinksHelper(htv, W2CT(pcwszDefInf), W2CT(pcwszIns), W2CT(pcwszFixPath),
  661. W2CT(pcwszNewPath), fIgnoreOffline);
  662. }
  663. BOOL WINAPI NewUrlA(HWND htv, LPCSTR pszExtractPath, DWORD dwPlatformID, DWORD dwMode)
  664. {
  665. USES_CONVERSION;
  666. return newUrlHelper(htv, A2CT(pszExtractPath), dwPlatformID, dwMode);
  667. }
  668. BOOL WINAPI NewUrlW(HWND htv, LPCWSTR pcwszExtractPath, DWORD dwPlatformID, DWORD dwMode)
  669. {
  670. USES_CONVERSION;
  671. return newUrlHelper(htv, W2CT(pcwszExtractPath), dwPlatformID, dwMode);
  672. }
  673. BOOL WINAPI NewFolder(HWND htv)
  674. {
  675. LPFAVSTRUC pfsNew;
  676. AEFAVPARAMS aefp;
  677. int iResult;
  678. ASSERT(isFavoriteItem(htv, TreeView_GetSelection(htv)) == S_OK);
  679. pfsNew = pfsNew->CreateNew(htv);
  680. if (pfsNew == NULL)
  681. goto Fail;
  682. pfsNew->wType = FTYPE_FOLDER;
  683. ZeroMemory(&aefp, sizeof(aefp));
  684. aefp.pfs = pfsNew;
  685. aefp.fQL = FALSE;
  686. aefp.hwndErrorParent = GetParent(htv);
  687. aefp.htv = htv;
  688. aefp.hti = TreeView_GetSelection(htv);
  689. aefp.pszExtractPath = NULL;
  690. aefp.dwPlatformID = PLATFORM_WIN32;
  691. aefp.dwMode = IEM_CORP;
  692. iResult = (int) DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FAVPOPUP), GetParent(htv),
  693. addEditFavoriteDlgProc, (LPARAM)&aefp);
  694. if (iResult == IDCANCEL)
  695. goto Fail;
  696. pfsNew->Add(htv, NULL);
  697. return TRUE;
  698. Fail:
  699. if (pfsNew != NULL)
  700. pfsNew->Delete();
  701. return FALSE;
  702. }
  703. BOOL WINAPI ModifyFavoriteA(HWND htv, HTREEITEM hti, LPCSTR pszExtractPath, LPCSTR pszPrevExtractPath,
  704. DWORD dwPlatformID, DWORD dwMode)
  705. {
  706. USES_CONVERSION;
  707. return modifyFavoriteHelper(htv, hti, A2CT(pszExtractPath), A2CT(pszPrevExtractPath), dwPlatformID, dwMode);
  708. }
  709. BOOL WINAPI ModifyFavoriteW(HWND htv, HTREEITEM hti, LPCWSTR pcwszExtractPath, LPCWSTR pcwszPrevExtractPath,
  710. DWORD dwPlatformID, DWORD dwMode)
  711. {
  712. USES_CONVERSION;
  713. return modifyFavoriteHelper(htv, hti, W2CT(pcwszExtractPath), W2CT(pcwszPrevExtractPath), dwPlatformID, dwMode);
  714. }
  715. BOOL WINAPI DeleteFavoriteA(HWND htv, HTREEITEM hti, LPCSTR pszExtractPath)
  716. {
  717. USES_CONVERSION;
  718. return deleteFavoriteHelper(htv, hti, A2CT(pszExtractPath));
  719. }
  720. BOOL WINAPI DeleteFavoriteW(HWND htv, HTREEITEM hti, LPCWSTR pcwszExtractPath)
  721. {
  722. USES_CONVERSION;
  723. return deleteFavoriteHelper(htv, hti, W2CT(pcwszExtractPath));
  724. }
  725. BOOL WINAPI MoveUpFavorite(HWND htv, HTREEITEM hti)
  726. {
  727. HTREEITEM htiBrother1, htiBrother2;
  728. htiBrother1 = TreeView_GetPrevSibling(htv, hti);
  729. if (htiBrother1 == NULL)
  730. return FALSE;
  731. htiBrother2 = TreeView_GetPrevSibling(htv, htiBrother1);
  732. if (htiBrother2 == NULL)
  733. htiBrother2 = TVI_FIRST;
  734. if (!importPath(htv, hti, &htiBrother2))
  735. return FALSE;
  736. ASSERT(htiBrother2 != NULL);
  737. TreeView_SelectItem(htv, htiBrother2);
  738. TreeView_DeleteItem(htv, hti);
  739. TreeView_EnsureVisible(htv, htiBrother2);
  740. return TRUE;
  741. }
  742. BOOL WINAPI MoveDownFavorite(HWND htv, HTREEITEM hti)
  743. {
  744. HTREEITEM htiBrother;
  745. htiBrother = TreeView_GetNextSibling(htv, hti);
  746. if (htiBrother == NULL)
  747. return FALSE;
  748. if (!importPath(htv, hti, &htiBrother))
  749. return FALSE;
  750. ASSERT(htiBrother != NULL);
  751. TreeView_SelectItem(htv, htiBrother);
  752. TreeView_DeleteItem(htv, hti);
  753. TreeView_EnsureVisible(htv, htiBrother);
  754. return TRUE;
  755. }
  756. BOOL WINAPI IsFavoriteItem(HWND htv, HTREEITEM hti)
  757. {
  758. return (isFavoriteItem(htv, hti) == S_OK);
  759. }
  760. UINT WINAPI GetFavoritesNumber(HWND htv, BOOL fQL /*= FALSE*/)
  761. {
  762. return SFav::GetNumber(htv, fQL);
  763. }
  764. UINT WINAPI GetFavoritesMaxNumber(BOOL fQL /*= FALSE*/)
  765. {
  766. return SFav::GetMaxNumber(fQL);
  767. }
  768. int WINAPI ImportFavoritesCmdA(HWND htv, LPCSTR pszExtractPath)
  769. {
  770. USES_CONVERSION;
  771. return importFavoritesCmdHelper(htv, A2CT(pszExtractPath));
  772. }
  773. int WINAPI ImportFavoritesCmdW(HWND htv, LPCWSTR pcwszExtractPath)
  774. {
  775. USES_CONVERSION;
  776. return importFavoritesCmdHelper(htv, W2CT(pcwszExtractPath));
  777. }
  778. void WINAPI ExportFavoritesA(HWND htv, LPCSTR pszIns, LPCSTR pszExtractPath, BOOL fFixUpPath)
  779. {
  780. USES_CONVERSION;
  781. exportFavoritesHelper(htv, A2CT(pszIns), A2CT(pszExtractPath), fFixUpPath);
  782. }
  783. void WINAPI ExportFavoritesW(HWND htv, LPCWSTR pcwszIns, LPCWSTR pcwszExtractPath, BOOL fFixUpPath)
  784. {
  785. USES_CONVERSION;
  786. exportFavoritesHelper(htv, W2CT(pcwszIns), W2CT(pcwszExtractPath), fFixUpPath);
  787. }
  788. void WINAPI ExportQuickLinksA(HWND htv, LPCSTR pszIns, LPCSTR pszExtractPath, BOOL fFixUpPath)
  789. {
  790. USES_CONVERSION;
  791. exportQuickLinksHelper(htv, A2CT(pszIns), A2CT(pszExtractPath), fFixUpPath);
  792. }
  793. void WINAPI ExportQuickLinksW(HWND htv, LPCWSTR pcwszIns, LPCWSTR pcwszExtractPath, BOOL fFixUpPath)
  794. {
  795. USES_CONVERSION;
  796. exportQuickLinksHelper(htv, W2CT(pcwszIns), W2CT(pcwszExtractPath), fFixUpPath);
  797. }
  798. void WINAPI GetFavoritesInfoTipA(LPNMTVGETINFOTIPA pGetInfoTipA)
  799. {
  800. NMTVGETINFOTIP GetInfoTip;
  801. ZeroMemory(&GetInfoTip, sizeof(GetInfoTip));
  802. GetInfoTip.pszText = (LPTSTR)LocalAlloc(LPTR, pGetInfoTipA->cchTextMax * sizeof(TCHAR));
  803. if (GetInfoTip.pszText != NULL)
  804. {
  805. getFavoritesInfoTipHelper(TVInfoTipA2T(pGetInfoTipA, &GetInfoTip));
  806. TVInfoTipT2A(&GetInfoTip, pGetInfoTipA);
  807. LocalFree(GetInfoTip.pszText);
  808. }
  809. }
  810. void WINAPI GetFavoritesInfoTipW(LPNMTVGETINFOTIPW pGetInfoTipW)
  811. {
  812. NMTVGETINFOTIP GetInfoTip;
  813. ZeroMemory(&GetInfoTip, sizeof(GetInfoTip));
  814. GetInfoTip.pszText = (LPTSTR)LocalAlloc(LPTR, pGetInfoTipW->cchTextMax * sizeof(TCHAR));
  815. if (GetInfoTip.pszText != NULL)
  816. {
  817. getFavoritesInfoTipHelper(TVInfoTipW2T(pGetInfoTipW, &GetInfoTip));
  818. TVInfoTipT2W(&GetInfoTip, pGetInfoTipW);
  819. LocalFree(GetInfoTip.pszText);
  820. }
  821. }
  822. BOOL WINAPI GetFavoriteUrlA(HWND htv, HTREEITEM hti, LPSTR pszUrl, DWORD cchSize)
  823. {
  824. LPTSTR pszUrlBuf = (LPTSTR)LocalAlloc(LPTR, cchSize * sizeof(TCHAR));
  825. BOOL fRet;
  826. if (pszUrlBuf == NULL)
  827. fRet = FALSE;
  828. else
  829. {
  830. fRet = getFavoriteUrlHelper(htv, hti, pszUrlBuf);
  831. if (fRet)
  832. T2Abux(pszUrlBuf, pszUrl);
  833. LocalFree(pszUrlBuf);
  834. }
  835. return fRet;
  836. }
  837. BOOL WINAPI GetFavoriteUrlW(HWND htv, HTREEITEM hti, LPWSTR pwszUrl, DWORD cchSize)
  838. {
  839. LPTSTR pszUrlBuf = (LPTSTR)LocalAlloc(LPTR, cchSize * sizeof(TCHAR));
  840. BOOL fRet;
  841. if (pszUrlBuf == NULL)
  842. fRet = FALSE;
  843. else
  844. {
  845. fRet = getFavoriteUrlHelper(htv, hti, pszUrlBuf);
  846. if (fRet)
  847. T2Wbux(pszUrlBuf, pwszUrl);
  848. LocalFree(pszUrlBuf);
  849. }
  850. return fRet;
  851. }
  852. void WINAPI ProcessFavSelChange(HWND hDlg, HWND hTv, LPNMTREEVIEW pnmtv)
  853. {
  854. LPFAVSTRUC pfs;
  855. if (HasFlag(pnmtv->itemNew.state, TVIS_BOLD)) {
  856. int rgids[] = { IDC_MODIFY, IDC_REMOVE, IDC_TESTFAVURL, IDC_FAVUP, IDC_FAVDOWN };
  857. EnsureDialogFocus(hDlg, rgids, countof(rgids), IDC_ADDURL);
  858. DisableDlgItems (hDlg, rgids, countof(rgids));
  859. }
  860. else {
  861. EnableDlgItem(hDlg, IDC_MODIFY);
  862. EnableDlgItem(hDlg, IDC_REMOVE);
  863. pfs = (LPFAVSTRUC)pnmtv->itemNew.lParam;
  864. if (pfs != NULL)
  865. EnableDlgItem2(hDlg, IDC_TESTFAVURL, (pfs->wType == FTYPE_URL));
  866. if (BST_CHECKED == IsDlgButtonChecked(hDlg, IDC_FAVONTOP)) {
  867. EnableDlgItem2(hDlg, IDC_FAVUP, (NULL != TreeView_GetPrevSibling(hTv, pnmtv->itemNew.hItem)));
  868. EnableDlgItem2(hDlg, IDC_FAVDOWN, (NULL != TreeView_GetNextSibling(hTv, pnmtv->itemNew.hItem)));
  869. }
  870. }
  871. EnableDlgItem2(hDlg, IDC_ADDFOLDER, IsFavoriteItem(hTv, pnmtv->itemNew.hItem));
  872. }
  873. /////////////////////////////////////////////////////////////////////////////
  874. // Implementation helper routines
  875. static BOOL migrateFavoritesHelper(LPCTSTR pszIns)
  876. {
  877. TCHAR szTitle[MAX_PATH],
  878. szUrl[INTERNET_MAX_URL_LENGTH],
  879. szKey[32];
  880. LPCTSTR pszTitle;
  881. LPTSTR pszBuffer;
  882. HANDLE hIns;
  883. DWORD dwInsSize;
  884. UINT i;
  885. // figure out if there are any favorites at all
  886. // NOTE: (andrewgu) szUrl serves as a mere buffer in the processing below.
  887. wnsprintf(szKey, countof(szKey), IK_TITLE_FMT, 1);
  888. if (InsIsKeyEmpty(IS_FAVORITESEX, szKey, pszIns)) {
  889. if (InsIsSectionEmpty(IS_FAVORITES, pszIns))
  890. return TRUE;
  891. }
  892. else
  893. return TRUE;
  894. WritePrivateProfileString(NULL, NULL, NULL, pszIns);
  895. hIns = CreateFile(pszIns, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
  896. if (hIns == INVALID_HANDLE_VALUE)
  897. return FALSE;
  898. dwInsSize = GetFileSize(hIns, NULL);
  899. ASSERT(dwInsSize != 0xFFFFFFFF);
  900. CloseHandle(hIns);
  901. pszBuffer = (LPTSTR)CoTaskMemAlloc(dwInsSize*sizeof(TCHAR));
  902. if (pszBuffer == NULL)
  903. return FALSE;
  904. ZeroMemory(pszBuffer, dwInsSize);
  905. GetPrivateProfileString(IS_FAVORITES, NULL, TEXT(""), pszBuffer, (UINT)dwInsSize, pszIns);
  906. ASSERT(*pszBuffer != TEXT('\0'));
  907. for (i = 1, pszTitle = pszBuffer; *pszTitle != TEXT('\0'); pszTitle += StrLen(pszTitle) + 1, i++) {
  908. InsGetString(IS_FAVORITES, pszTitle, szUrl, countof(szUrl), pszIns);
  909. wnsprintf(szKey, countof(szKey), IK_TITLE_FMT, i);
  910. StrCpy(szTitle, pszTitle);
  911. decodeFavName(szTitle, pszIns);
  912. WritePrivateProfileString(IS_FAVORITESEX, szKey, szTitle, pszIns);
  913. wnsprintf(szKey, countof(szKey), IK_URL_FMT, i);
  914. WritePrivateProfileString(IS_FAVORITESEX, szKey, szUrl, pszIns);
  915. }
  916. CoTaskMemFree(pszBuffer);
  917. return TRUE;
  918. }
  919. static void migrateToOldFavoritesHelper(LPCTSTR pszIns)
  920. {
  921. TCHAR szTitle[MAX_PATH],
  922. szUrl[INTERNET_MAX_URL_LENGTH],
  923. szKey[32];
  924. WritePrivateProfileString(IS_FAVORITES, NULL, NULL, pszIns);
  925. for (UINT i = 1; TRUE; i++) {
  926. wnsprintf(szKey, countof(szKey), IK_TITLE_FMT, i);
  927. InsGetString(IS_FAVORITESEX, szKey, szTitle, countof(szTitle), pszIns);
  928. if (szTitle[0] == TEXT('\0'))
  929. break;
  930. wnsprintf(szKey, countof(szKey), IK_URL_FMT, i);
  931. InsGetString(IS_FAVORITESEX, szKey, szUrl, countof(szUrl), pszIns);
  932. encodeFavName(szTitle, pszIns);
  933. WritePrivateProfileString(IS_FAVORITES, szTitle, szUrl, pszIns);
  934. }
  935. WritePrivateProfileString(NULL, NULL, NULL, pszIns);
  936. }
  937. static int importFavoritesHelper(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns,
  938. LPCTSTR pszFixPath, LPCTSTR pszNewPath, BOOL fIgnoreOffline)
  939. {
  940. return importItems(htv, pszDefInf, pszIns, pszFixPath, pszNewPath, fIgnoreOffline);
  941. }
  942. static int importQuickLinksHelper(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns,
  943. LPCTSTR pszFixPath, LPCTSTR pszNewPath, BOOL fIgnoreOffline)
  944. {
  945. return importItems(htv, pszDefInf, pszIns, pszFixPath, pszNewPath, fIgnoreOffline, TRUE);
  946. }
  947. static BOOL newUrlHelper(HWND htv, LPCTSTR pszExtractPath, DWORD dwPlatformID, DWORD dwMode)
  948. {
  949. LPFAVSTRUC pfsNew;
  950. AEFAVPARAMS aefp;
  951. HTREEITEM htiSel;
  952. int iResult;
  953. BOOL fQL;
  954. htiSel = TreeView_GetSelection(htv);
  955. fQL = (isFavoriteItem(htv, htiSel) != S_OK);
  956. pfsNew = pfsNew->CreateNew(htv, fQL);
  957. if (pfsNew == NULL)
  958. goto Fail;
  959. pfsNew->wType = FTYPE_URL;
  960. ZeroMemory(&aefp, sizeof(aefp));
  961. aefp.pfs = pfsNew;
  962. aefp.fQL = fQL;
  963. aefp.hwndErrorParent = GetParent(htv);
  964. aefp.htv = htv;
  965. aefp.hti = htiSel;
  966. aefp.pszExtractPath = pszExtractPath;
  967. aefp.dwPlatformID = dwPlatformID;
  968. aefp.dwMode = dwMode;
  969. iResult = (int) DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FAVPOPUP), GetParent(htv),
  970. addEditFavoriteDlgProc, (LPARAM)&aefp);
  971. if (iResult == IDCANCEL)
  972. goto Fail;
  973. pfsNew->Add(htv, htiSel);
  974. return TRUE;
  975. Fail:
  976. if (pfsNew != NULL)
  977. pfsNew->Delete();
  978. return FALSE;
  979. }
  980. static BOOL modifyFavoriteHelper(HWND htv, HTREEITEM hti, LPCTSTR pszExtractPath, LPCTSTR pszPrevExtractPath,
  981. DWORD dwPlatformID, DWORD dwMode)
  982. {
  983. LPFAVSTRUC pfs;
  984. AEFAVPARAMS aefp;
  985. int iResult;
  986. pfs = getItem(htv, hti);
  987. if (pfs == NULL)
  988. return FALSE;
  989. ZeroMemory(&aefp, sizeof(aefp));
  990. aefp.pfs = pfs;
  991. aefp.fQL = FALSE;
  992. aefp.hwndErrorParent = GetParent(htv);
  993. aefp.htv = htv;
  994. aefp.hti = TreeView_GetParent(htv, hti);
  995. aefp.pszExtractPath = pszExtractPath;
  996. aefp.pszPrevExtractPath = pszPrevExtractPath;
  997. aefp.dwPlatformID = dwPlatformID;
  998. aefp.dwMode = dwMode;
  999. iResult = (int) DialogBoxParam(g_hInst, MAKEINTRESOURCE(IDD_FAVPOPUP), GetParent(htv),
  1000. addEditFavoriteDlgProc, (LPARAM)&aefp);
  1001. if (iResult == IDCANCEL)
  1002. return FALSE;
  1003. if (pfs->pTvItem != NULL) {
  1004. TreeView_SetItem(htv, pfs->pTvItem);
  1005. if (pfs->pTvItem->hItem != NULL)
  1006. TreeView_SelectItem(htv, pfs->pTvItem->hItem);
  1007. }
  1008. return TRUE;
  1009. }
  1010. static BOOL deleteFavoriteHelper(HWND htv, HTREEITEM hti, LPCTSTR pszExtractPath)
  1011. {
  1012. LPFAVSTRUC pfs;
  1013. HTREEITEM htiChild;
  1014. htiChild = TreeView_GetChild(htv, hti);
  1015. if (htiChild != NULL) {
  1016. HTREEITEM htiSibling;
  1017. while ((htiSibling = TreeView_GetNextSibling(htv, htiChild)) != NULL)
  1018. deleteFavoriteHelper(htv, htiSibling, pszExtractPath);
  1019. deleteFavoriteHelper(htv, htiChild, pszExtractPath);
  1020. }
  1021. pfs = getItem(htv, hti);
  1022. if (pfs == NULL)
  1023. return FALSE;
  1024. pfs->Free(htv, (isFavoriteItem(htv, hti) != S_OK), pszExtractPath);
  1025. return TRUE;
  1026. }
  1027. static int importFavoritesCmdHelper(HWND htv, LPCTSTR pszExtractPath)
  1028. {
  1029. LPFAVSTRUC pfsFolder;
  1030. TCHAR szFolder[MAX_PATH],
  1031. szTitle[MAX_PATH];
  1032. pfsFolder = getFolderItem(htv, TreeView_GetSelection(htv));
  1033. if (pfsFolder == NULL || pfsFolder->pTvItem == NULL || pfsFolder->pTvItem->hItem == NULL)
  1034. return 0;
  1035. LoadString(g_hInst, IDS_BROWSEIMPORT, szTitle, countof(szTitle));
  1036. if (!BrowseForFolder(htv, szFolder, szTitle))
  1037. return 0;
  1038. if (szFolder[0] == TEXT('\0'))
  1039. return 0;
  1040. importPath (htv, pfsFolder->pTvItem->hItem, szFolder, pszExtractPath);
  1041. TreeView_Expand(htv, pfsFolder->pTvItem->hItem, TVE_EXPAND);
  1042. return pfsFolder->GetNumber(htv);
  1043. }
  1044. static void exportFavoritesHelper(HWND htv, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath /*= TRUE */)
  1045. {
  1046. LPFAVSTRUC pfs;
  1047. int i;
  1048. WritePrivateProfileString(IS_FAVORITESEX, NULL, NULL, pszIns);
  1049. pfs = pfs->GetFirst(htv);
  1050. if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1051. return;
  1052. i = exportItems(htv, pfs->pTvItem->hItem, pszIns, pszExtractPath, fFixUpPath);
  1053. // if no favorites, write out a flag so we don't repopulate with default favorites next time around
  1054. InsWriteBool(IS_BRANDING, IK_NOFAVORITES, (i == 1), pszIns);
  1055. }
  1056. static void exportQuickLinksHelper(HWND htv, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath /*= TRUE */)
  1057. {
  1058. LPFAVSTRUC pfs;
  1059. int i;
  1060. pfs = pfs->GetFirst(htv, TRUE);
  1061. if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1062. return;
  1063. i = exportItems(htv, pfs->pTvItem->hItem, pszIns, pszExtractPath, fFixUpPath);
  1064. // if no links, write out a flag so we don't repopulate with default links next time around
  1065. InsWriteBool(IS_BRANDING, IK_NOLINKS, (i == 1), pszIns);
  1066. // clear out any stuff that might be left over
  1067. SFav favEmpty;
  1068. for (i = (i >= 0) ? i : 1; (UINT)i < pfs->GetMaxNumber(TRUE); i++)
  1069. favEmpty.Save(NULL, i, pszIns, NULL, TRUE, fFixUpPath);
  1070. }
  1071. static void getFavoritesInfoTipHelper(LPNMTVGETINFOTIP pGetInfoTip)
  1072. {
  1073. LPFAVSTRUC pfs;
  1074. static TCHAR s_szFormat[80],
  1075. s_szAbsent[30],
  1076. s_szOfflineOn[30], s_szOfflineOff[30],
  1077. s_szEllipsis[] = TEXT("...");
  1078. TCHAR szBuffer[2 * MAX_PATH],
  1079. rgszAux [4][30];
  1080. LPCTSTR rgpszAux[4];
  1081. if (s_szFormat[0] == TEXT('\0')) {
  1082. LoadString(g_hInst, IDS_FAVS_TOOLTIPFORMAT, s_szFormat, countof(s_szFormat));
  1083. LoadString(g_hInst, IDS_FAVS_ABSENT, s_szAbsent, countof(s_szAbsent));
  1084. LoadString(g_hInst, IDS_FAVS_OFFLINE, s_szOfflineOn, countof(s_szAbsent));
  1085. LoadString(g_hInst, IDS_FAVS_NOOFFLINE, s_szOfflineOff, countof(s_szOfflineOff));
  1086. }
  1087. ASSERT(pGetInfoTip != NULL);
  1088. pfs = (LPFAVSTRUC)pGetInfoTip->lParam;
  1089. if (pfs == NULL || pfs->wType != FTYPE_URL)
  1090. {
  1091. StrCpyN(pGetInfoTip->pszText, pfs != NULL ? pfs->pszName : TEXT(""), pGetInfoTip->cchTextMax);
  1092. return;
  1093. }
  1094. ASSERT(pfs->pszName != NULL && pfs->pszUrl != NULL);
  1095. rgpszAux[0] = pfs->pszName;
  1096. rgpszAux[1] = pfs->pszUrl;
  1097. rgpszAux[2] = pfs->pszIconFile;
  1098. rgpszAux[3] = pfs->fOffline ? s_szOfflineOn : s_szOfflineOff;
  1099. for (UINT i = 0; i < countof(rgszAux); i++)
  1100. {
  1101. if (rgpszAux[i] == NULL)
  1102. StrCpy(rgszAux[i], s_szAbsent);
  1103. else
  1104. {
  1105. if (StrLen(rgpszAux[i]) < countof(rgszAux[i]))
  1106. StrCpy(rgszAux[i], rgpszAux[i]);
  1107. else
  1108. {
  1109. StrCpyN(rgszAux[i], rgpszAux[i], countof(rgszAux[i]) - countof(s_szEllipsis) + 1);
  1110. StrCpy(&rgszAux[i][countof(rgszAux[i]) - countof(s_szEllipsis)], s_szEllipsis);
  1111. }
  1112. }
  1113. }
  1114. wnsprintf(szBuffer, countof(szBuffer), s_szFormat, rgszAux[0], rgszAux[1], rgszAux[2],
  1115. rgszAux[3]);
  1116. StrCpyN(pGetInfoTip->pszText, szBuffer, pGetInfoTip->cchTextMax);
  1117. }
  1118. static BOOL getFavoriteUrlHelper(HWND htv, HTREEITEM hti, LPTSTR pszUrl)
  1119. {
  1120. LPFAVSTRUC pfs = getItem(htv, hti);
  1121. BOOL fRet = FALSE;
  1122. if ((pfs != NULL) && (pfs->pszUrl != NULL))
  1123. {
  1124. fRet = TRUE;
  1125. StrCpy(pszUrl, pfs->pszUrl);
  1126. }
  1127. return fRet;
  1128. }
  1129. int importItems(HWND htv, LPCTSTR pszDefInf, LPCTSTR pszIns, LPCTSTR pszFixPath, LPCTSTR pszNewPath,
  1130. BOOL fIgnoreOffline, BOOL fQL /*= FALSE */)
  1131. {
  1132. LPFAVSTRUC pfs, pfsCur;
  1133. TCHAR szKey[32];
  1134. UINT i;
  1135. pfs = pfs->GetFirst(htv, fQL);
  1136. if (pfs != NULL && pfs->pTvItem != NULL && pfs->pTvItem->hItem != NULL) {
  1137. DeleteFavorite(htv, pfs->pTvItem->hItem, pszNewPath);
  1138. ASSERT(pfs->GetNumber(htv, fQL) == 0);
  1139. }
  1140. pfs = pfs->CreateNew(htv, fQL);
  1141. if (pfs == NULL)
  1142. return 0;
  1143. ASSERT(pfs == pfs->GetFirst(htv, fQL));
  1144. pfs->wType = FTYPE_FOLDER;
  1145. if (!pfs->Expand())
  1146. return 0;
  1147. LoadString(g_hInst, fQL ? IDS_LINKS : IDS_FAVFOLDER, pfs->pszName, MAX_PATH);
  1148. pfs->SetTVI();
  1149. pfs->pTvItem->stateMask = pfs->pTvItem->state = TVIS_BOLD;
  1150. pfs->Shrink();
  1151. TreeView_SelectItem(htv, NULL);
  1152. pfs->Add(htv, NULL);
  1153. ASSERT(pfs->pTvItem != NULL && pfs->pTvItem->hItem != NULL);
  1154. for (i = 1; TRUE; i++) {
  1155. pfsCur = pfs->CreateNew(htv, fQL);
  1156. if (pfsCur == NULL)
  1157. break;
  1158. if (pfsCur->Load(i, pszIns, fQL, pszFixPath, pszNewPath, fIgnoreOffline) != S_OK)
  1159. break;
  1160. pfsCur->Add(htv, pfs->pTvItem->hItem);
  1161. }
  1162. // NOTE: (andrewgu) this is an ugly special case when there are no quick links in the ins.
  1163. // it's a brief version of SFav::Load which only loads name and url fields. there are two
  1164. // alternative ways of doing this with SFav::Load. one is to special case the section to
  1165. // IS_STRINGS if extension of pszIns is *.inf, another is to make the section an in-parameter
  1166. // of SFav::Load.
  1167. if (i == 1 && !InsGetBool(IS_BRANDING, fQL ? IK_NOLINKS : IK_NOFAVORITES, FALSE, pszIns))
  1168. for (; TRUE; i++) {
  1169. pfsCur = pfsCur->CreateNew(htv, fQL);
  1170. if (pfsCur == NULL)
  1171. break;
  1172. pfsCur->wType = FTYPE_URL;
  1173. if (!pfsCur->Expand())
  1174. return pfs->GetNumber(htv, fQL);
  1175. *pfsCur->pszIconFile = TEXT('\0');
  1176. wnsprintf(szKey, countof(szKey), fQL ? IK_QUICKLINK_NAME : IK_TITLE_FMT, i);
  1177. InsGetSubstString(fQL ? IS_URL : IS_FAVORITESEX, szKey, pfsCur->pszName, MAX_PATH, pszDefInf);
  1178. if (*pfsCur->pszName == TEXT('\0')) {
  1179. pfsCur->Delete();
  1180. break;
  1181. }
  1182. StrCat(pfsCur->pszName, DOT_URL);
  1183. wnsprintf(szKey, countof(szKey), fQL ? IK_QUICKLINK_URL : IK_URL_FMT, i);
  1184. InsGetSubstString(fQL ? IS_URL : IS_FAVORITESEX, szKey, pfsCur->pszUrl, INTERNET_MAX_URL_LENGTH, pszDefInf);
  1185. ASSERT(*pfsCur->pszUrl != TEXT('\0'));
  1186. pfsCur->SetTVI();
  1187. pfsCur->Shrink();
  1188. pfsCur->Add(htv, pfs->pTvItem->hItem);
  1189. }
  1190. TreeView_Expand(htv, pfs->pTvItem->hItem, TVE_EXPAND);
  1191. return pfs->GetNumber(htv, fQL);
  1192. }
  1193. INT_PTR CALLBACK addEditFavoriteDlgProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
  1194. {
  1195. LPAEFAVPARAMS paefp;
  1196. LPFAVSTRUC pfs;
  1197. TCHAR szName[MAX_PATH],
  1198. szIconFile[INTERNET_MAX_URL_LENGTH];
  1199. HWND hCtrl;
  1200. BOOL fResult,
  1201. fEnable, fWasEnabled;
  1202. fResult = FALSE;
  1203. switch (message) {
  1204. case WM_INITDIALOG:
  1205. paefp = (LPAEFAVPARAMS)lParam;
  1206. SetWindowLongPtr(hDlg, DWLP_USER, (LONG_PTR)paefp);
  1207. //----- Initialize contols -----
  1208. EnableDBCSChars(hDlg, IDE_FAVNAME);
  1209. EnableDBCSChars(hDlg, IDE_FAVURL);
  1210. EnableDBCSChars(hDlg, IDE_FAVICON);
  1211. Edit_LimitText(GetDlgItem(hDlg, IDE_FAVNAME), _MAX_FNAME);
  1212. Edit_LimitText(GetDlgItem(hDlg, IDE_FAVURL), INTERNET_MAX_URL_LENGTH-1);
  1213. Edit_LimitText(GetDlgItem(hDlg, IDE_FAVICON), _MAX_FNAME);
  1214. //----- Initialize SFav structure associated with this dialog -----
  1215. fResult = (paefp == NULL || (paefp->pfs != NULL ? !paefp->pfs->Expand() : TRUE));
  1216. if (fResult) {
  1217. EndDialog(hDlg, IDCANCEL);
  1218. break;
  1219. }
  1220. pfs = paefp->pfs;
  1221. //----- Initialize contols (Part II) -----
  1222. if (paefp->dwPlatformID != PLATFORM_WIN32) {
  1223. EnableWindow(GetDlgItem(hDlg, IDC_FAVICON), FALSE);
  1224. EnableWindow(GetDlgItem(hDlg, IDE_FAVICON), FALSE);
  1225. EnableWindow(GetDlgItem(hDlg, IDC_FAVICONBROWSE), FALSE);
  1226. EnableWindow(GetDlgItem(hDlg, IDC_AVAILOFFLINE), FALSE);
  1227. }
  1228. else
  1229. if (!HasFlag(paefp->dwMode, (IEM_CORP | IEM_PROFMGR)) && pfs->wType == FTYPE_URL)
  1230. EnableWindow(GetDlgItem(hDlg, IDC_AVAILOFFLINE), FALSE);
  1231. if (pfs->wType == FTYPE_FOLDER) {
  1232. EnableWindow(GetDlgItem(hDlg, IDC_FAVURL), FALSE);
  1233. EnableWindow(GetDlgItem(hDlg, IDE_FAVURL), FALSE);
  1234. if (paefp->dwPlatformID == PLATFORM_WIN32) {
  1235. EnableWindow(GetDlgItem(hDlg, IDC_FAVICON), FALSE);
  1236. EnableWindow(GetDlgItem(hDlg, IDE_FAVICON), FALSE);
  1237. EnableWindow(GetDlgItem(hDlg, IDC_FAVICONBROWSE), FALSE);
  1238. EnableWindow(GetDlgItem(hDlg, IDC_AVAILOFFLINE), FALSE);
  1239. }
  1240. else {
  1241. ASSERT(!IsWindowEnabled(GetDlgItem(hDlg, IDC_FAVICON)));
  1242. ASSERT(!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVICON)));
  1243. ASSERT(!IsWindowEnabled(GetDlgItem(hDlg, IDC_FAVICONBROWSE)));
  1244. ASSERT(!IsWindowEnabled(GetDlgItem(hDlg, IDC_AVAILOFFLINE)));
  1245. }
  1246. }
  1247. //----- Populate controls -----
  1248. if (pfs->pszName == NULL || *pfs->pszName == TEXT('\0')) {
  1249. UINT nID;
  1250. if (pfs->wType == FTYPE_URL)
  1251. nID = (!paefp->fQL ? IDS_NEW : IDS_NEWQL);
  1252. else {
  1253. ASSERT(pfs->wType == FTYPE_FOLDER);
  1254. nID = IDS_NEWFOLDER;
  1255. }
  1256. LoadString(g_hInst, nID, pfs->pszName, MAX_PATH);
  1257. }
  1258. SetDlgItemText(hDlg, IDE_FAVNAME, pfs->pszName);
  1259. if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVURL)))
  1260. ;
  1261. else {
  1262. if (pfs->pszUrl == NULL || *pfs->pszUrl == TEXT('\0'))
  1263. StrCpy(pfs->pszUrl, TEXT("http://www."));
  1264. SetDlgItemText(hDlg, IDE_FAVURL, pfs->pszUrl);
  1265. }
  1266. if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVICON)))
  1267. ;
  1268. else
  1269. if (pfs->pszIconFile != NULL && *pfs->pszIconFile != TEXT('\0'))
  1270. SetDlgItemText(hDlg, IDE_FAVICON, pfs->pszIconFile);
  1271. if (!IsWindowEnabled(GetDlgItem(hDlg, IDC_AVAILOFFLINE)))
  1272. ;
  1273. else
  1274. if (pfs->fOffline)
  1275. CheckDlgButton(hDlg, IDC_AVAILOFFLINE, BST_CHECKED);
  1276. fResult = TRUE;
  1277. break;
  1278. case WM_COMMAND:
  1279. switch (LOWORD(wParam)) {
  1280. case IDE_FAVNAME:
  1281. case IDE_FAVURL:
  1282. case IDE_FAVICON:
  1283. switch (HIWORD(wParam)) {
  1284. case EN_CHANGE:
  1285. paefp = (LPAEFAVPARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
  1286. hCtrl = GetDlgItem(hDlg, IDOK);
  1287. fWasEnabled = IsWindowEnabled(hCtrl);
  1288. fEnable = (GetWindowTextLength(GetDlgItem(hDlg, IDE_FAVNAME)) > 0);
  1289. if (paefp->pfs->wType == FTYPE_URL)
  1290. fEnable &= (GetWindowTextLength(GetDlgItem(hDlg, IDE_FAVURL)) > 0);
  1291. if (fEnable != fWasEnabled)
  1292. EnableWindow(hCtrl, fEnable);
  1293. fResult = TRUE;
  1294. break;
  1295. }
  1296. break;
  1297. case IDC_FAVICONBROWSE:
  1298. GetDlgItemText(hDlg, IDE_FAVICON, szIconFile, countof(szIconFile));
  1299. if (!BrowseForFile(hDlg, szIconFile, countof(szIconFile), GFN_ICO))
  1300. break;
  1301. SetDlgItemText(hDlg, IDE_FAVICON, szIconFile);
  1302. fResult = TRUE;
  1303. break;
  1304. case IDOK:
  1305. paefp = (LPAEFAVPARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
  1306. if (!CheckField(hDlg, IDE_FAVNAME, FC_NONNULL | FC_PATH, PIVP_FILENAME_ONLY)) {
  1307. fResult = FALSE;
  1308. break;
  1309. }
  1310. if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVURL)))
  1311. ;
  1312. else
  1313. if (!CheckField(hDlg, IDE_FAVURL, FC_NONNULL | FC_URL)) {
  1314. fResult = FALSE;
  1315. break;
  1316. }
  1317. if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVICON)))
  1318. ;
  1319. else
  1320. if (!CheckField(hDlg, IDE_FAVICON, FC_URL | FC_FILE | FC_EXISTS)) {
  1321. fResult = FALSE;
  1322. break;
  1323. }
  1324. GetDlgItemText(hDlg, IDE_FAVNAME, szName, countof(szName));
  1325. StrRemoveWhitespace(szName);
  1326. pfs = findByName(paefp->htv, paefp->hti, szName);
  1327. if (pfs != NULL && pfs != paefp->pfs) {
  1328. HWND hCtrl;
  1329. ErrorMessageBox(paefp->hwndErrorParent, IDS_FAV_ERR_DUPLICATE);
  1330. hCtrl = GetDlgItem(hDlg, IDE_FAVNAME);
  1331. Edit_SetSel(hCtrl, 0, -1);
  1332. SetFocus(hCtrl);
  1333. fResult = FALSE;
  1334. break;
  1335. }
  1336. pfs = paefp->pfs; // reassign pfs back to paefp->pfs
  1337. ASSERT(pfs->pszName != NULL);
  1338. StrCpy(pfs->pszName, szName);
  1339. if (pfs->pszUrl != NULL)
  1340. if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVURL)))
  1341. *pfs->pszUrl = TEXT('\0');
  1342. else {
  1343. GetDlgItemText(hDlg, IDE_FAVURL, pfs->pszUrl, INTERNET_MAX_URL_LENGTH);
  1344. StrRemoveWhitespace(pfs->pszUrl);
  1345. }
  1346. if (pfs->pszIconFile != NULL)
  1347. if (!IsWindowEnabled(GetDlgItem(hDlg, IDE_FAVICON)))
  1348. *pfs->pszIconFile = TEXT('\0');
  1349. else {
  1350. GetDlgItemText(hDlg, IDE_FAVICON, szIconFile, countof(szIconFile));
  1351. StrRemoveWhitespace(szIconFile);
  1352. ASSERT(paefp->pszExtractPath != NULL);
  1353. if (*pfs->pszIconFile != TEXT('\0') && StrCmpI(szIconFile, pfs->pszIconFile) != 0)
  1354. {
  1355. if (PathIsPrefix(paefp->pszPrevExtractPath, pfs->pszIconFile))
  1356. DeleteFile(pfs->pszIconFile);
  1357. else
  1358. DeleteFileInDir(pfs->pszIconFile, paefp->pszExtractPath);
  1359. }
  1360. extractIcon(szIconFile, 1, paefp->pszExtractPath, pfs->pszIconFile, INTERNET_MAX_URL_LENGTH);
  1361. }
  1362. pfs->fOffline = IsWindowEnabled(GetDlgItem(hDlg, IDC_AVAILOFFLINE)) &&
  1363. (IsDlgButtonChecked(hDlg, IDC_AVAILOFFLINE) == BST_CHECKED);
  1364. pfs->SetTVI();
  1365. EndDialog(hDlg, IDOK);
  1366. fResult = TRUE;
  1367. break;
  1368. case IDCANCEL:
  1369. EndDialog(hDlg, IDCANCEL);
  1370. fResult = TRUE;
  1371. break;
  1372. }
  1373. break;
  1374. case WM_DESTROY:
  1375. paefp = (LPAEFAVPARAMS)GetWindowLongPtr(hDlg, DWLP_USER);
  1376. if (paefp != NULL && paefp->pfs != NULL)
  1377. paefp->pfs->Shrink();
  1378. break;
  1379. }
  1380. return fResult;
  1381. }
  1382. LPFAVSTRUC getItem(HWND htv, HTREEITEM hti)
  1383. {
  1384. LPFAVSTRUC pfsResult;
  1385. TV_ITEM tvi;
  1386. if (htv == NULL || hti == NULL)
  1387. return NULL;
  1388. ZeroMemory(&tvi, sizeof(tvi));
  1389. tvi.mask = TVIF_PARAM;
  1390. tvi.hItem = hti;
  1391. TreeView_GetItem(htv, &tvi);
  1392. pfsResult = (LPFAVSTRUC)tvi.lParam;
  1393. if (pfsResult == NULL || pfsResult->pTvItem == NULL || pfsResult->pTvItem->hItem == NULL)
  1394. return NULL;
  1395. ASSERT(pfsResult->pTvItem->hItem == hti);
  1396. return pfsResult;
  1397. }
  1398. LPFAVSTRUC getFolderItem(HWND htv, HTREEITEM hti)
  1399. {
  1400. LPFAVSTRUC pfsResult;
  1401. if (htv == NULL || hti == NULL)
  1402. return NULL;
  1403. pfsResult = getItem(htv, hti);
  1404. if (pfsResult == NULL)
  1405. return NULL;
  1406. if (pfsResult->wType != FTYPE_FOLDER) {
  1407. pfsResult = getItem(htv, TreeView_GetParent(htv, hti));
  1408. if (pfsResult == NULL)
  1409. return NULL;
  1410. }
  1411. ASSERT(pfsResult->wType == FTYPE_FOLDER);
  1412. return pfsResult;
  1413. }
  1414. LPFAVSTRUC findByName(HWND htv, HTREEITEM hti, LPCTSTR pszName)
  1415. {
  1416. LPFAVSTRUC pfs;
  1417. HTREEITEM htiCur;
  1418. TCHAR szFolders[MAX_PATH];
  1419. LPTSTR pszFile;
  1420. if (pszName == NULL)
  1421. return NULL;
  1422. StrCpy(szFolders, pszName);
  1423. pszFile = PathFindFileName(szFolders);
  1424. if (pszFile == szFolders)
  1425. pfs = getFolderItem(htv, hti);
  1426. else {
  1427. *(pszFile-1) = TEXT('\0');
  1428. pszName = pszFile;
  1429. pfs = findPath(htv, hti, szFolders);
  1430. }
  1431. if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1432. return NULL;
  1433. for (htiCur = TreeView_GetChild(htv, pfs->pTvItem->hItem);
  1434. htiCur != NULL;
  1435. htiCur = TreeView_GetNextSibling(htv, htiCur)) {
  1436. pfs = getItem(htv, htiCur);
  1437. if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1438. return NULL;
  1439. if (StrCmpI(pfs->pszName, pszName) == 0)
  1440. break;
  1441. }
  1442. return (htiCur != NULL ? pfs : NULL);
  1443. }
  1444. LPFAVSTRUC findPath(HWND htv, HTREEITEM hti, LPCTSTR pszFolders)
  1445. {
  1446. LPFAVSTRUC pfsFirst,
  1447. pfsCur;
  1448. HTREEITEM htiCur;
  1449. TCHAR szPathChunk[MAX_PATH];
  1450. LPCTSTR pszCur, pszNext;
  1451. pfsFirst = pfsFirst->GetFirst(htv);
  1452. if (pfsFirst == NULL)
  1453. return NULL;
  1454. if (hti != NULL) {
  1455. pfsCur = getFolderItem(htv, hti);
  1456. if (pfsCur == NULL)
  1457. return NULL;
  1458. }
  1459. else
  1460. pfsCur = pfsFirst;
  1461. if (pfsCur->pTvItem == NULL || pfsCur->pTvItem->hItem == NULL)
  1462. return NULL;
  1463. if (pszFolders == NULL)
  1464. return pfsCur;
  1465. htiCur = pfsCur->pTvItem->hItem;
  1466. for (pszCur = pszFolders, pszNext = PathFindNextComponent(pszCur);
  1467. pszNext != NULL;
  1468. pszCur = pszNext, pszNext = PathFindNextComponent(pszCur)) {
  1469. ASSERT(pszNext-1 > pszCur);
  1470. StrCpyN(szPathChunk, pszCur, (int)(pszNext-pszCur) + (*pszNext != TEXT('\0') ? 0 : 1));
  1471. // determine if there is an object already for this path chunk
  1472. pfsCur = findByName(htv, htiCur, szPathChunk);
  1473. if (pfsCur == NULL ||
  1474. pfsCur->wType != FTYPE_FOLDER ||
  1475. pfsCur->pTvItem == NULL || pfsCur->pTvItem->hItem == NULL)
  1476. return NULL;
  1477. }
  1478. return (pszNext == NULL ? pfsCur : NULL);
  1479. }
  1480. HRESULT isFavoriteItem(HWND htv, HTREEITEM hti)
  1481. {
  1482. LPFAVSTRUC pfs;
  1483. HTREEITEM htiCur, htiNext;
  1484. if (htv == NULL || hti == NULL)
  1485. return E_INVALIDARG;
  1486. for (htiCur = TreeView_GetParent(htv, hti), htiNext = TreeView_GetParent(htv, htiCur);
  1487. htiNext != NULL;
  1488. htiCur = htiNext, htiNext = TreeView_GetParent(htv, htiCur))
  1489. ;
  1490. if (htiCur == NULL)
  1491. htiCur = hti;
  1492. pfs = getItem(htv, htiCur);
  1493. if (pfs == NULL)
  1494. return E_FAIL;
  1495. return (pfs == pfs->GetFirst(htv) ? S_OK : S_FALSE);
  1496. }
  1497. LPFAVSTRUC createFolderItems(HWND htv, HTREEITEM hti, LPCTSTR pszFolders)
  1498. {
  1499. LPFAVSTRUC pfs;
  1500. HTREEITEM htiCur;
  1501. TCHAR szPathChunk[MAX_PATH];
  1502. LPCTSTR pszCur, pszNext;
  1503. if (pszFolders == NULL)
  1504. return NULL;
  1505. pfs = getFolderItem(htv, hti);
  1506. if (pfs == NULL)
  1507. return NULL;
  1508. if (pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1509. return NULL;
  1510. htiCur = pfs->pTvItem->hItem;
  1511. for (pszCur = pszFolders, pszNext = PathFindNextComponent(pszCur);
  1512. pszNext != NULL;
  1513. pszCur = pszNext, pszNext = PathFindNextComponent(pszCur)) {
  1514. ASSERT(pszNext-1 > pszCur);
  1515. StrCpyN(szPathChunk, pszCur, (int)(pszNext-pszCur) + (*pszNext != TEXT('\0') ? 0 : 1));
  1516. // determine if there is an object already for this path chunk
  1517. pfs = findByName(htv, htiCur, szPathChunk);
  1518. if (pfs != NULL) {
  1519. if (pfs->wType != FTYPE_FOLDER)
  1520. return NULL;
  1521. if (pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1522. return NULL;
  1523. htiCur = pfs->pTvItem->hItem;
  1524. continue;
  1525. }
  1526. // create this path chunk as SFav object
  1527. pfs = pfs->CreateNew(htv);
  1528. if (pfs == NULL)
  1529. return NULL;
  1530. pfs->wType = FTYPE_FOLDER;
  1531. if (!pfs->Expand())
  1532. return NULL;
  1533. StrCpy(pfs->pszName, szPathChunk);
  1534. pfs->SetTVI();
  1535. pfs->Shrink();
  1536. pfs->Add(htv, htiCur);
  1537. ASSERT(pfs->pTvItem != NULL && pfs->pTvItem->hItem != NULL);
  1538. htiCur = pfs->pTvItem->hItem;
  1539. }
  1540. return pfs;
  1541. }
  1542. BOOL importPath(HWND htv, HTREEITEM htiFrom, HTREEITEM *phtiAfter)
  1543. {
  1544. LPFAVSTRUC pfs;
  1545. TV_INSERTSTRUCT tvins;
  1546. TV_ITEM tvi;
  1547. HTREEITEM htiFromCur, htiToCur,
  1548. htiParent, htiChild,
  1549. *phtiQueueFrom, *phtiQueueTo;
  1550. HRESULT hr;
  1551. UINT nNumber,
  1552. nFromHead, nFromTail,
  1553. nToHead, nToTail;
  1554. BOOL fQL,
  1555. fResult;
  1556. if (phtiAfter == NULL || *phtiAfter == NULL)
  1557. return FALSE;
  1558. hr = isFavoriteItem(htv, htiFrom);
  1559. if (FAILED(hr))
  1560. return FALSE;
  1561. fQL = (hr != S_OK);
  1562. // REVIEW: (andrewgu) actually, if we are to support this at all there needs to be a better
  1563. // default.
  1564. pfs = pfs->GetFirst(htv, fQL);
  1565. if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1566. return FALSE;
  1567. if (htiFrom == NULL) {
  1568. htiFrom = pfs->pTvItem->hItem;
  1569. ASSERT(*phtiAfter != TVI_FIRST);
  1570. }
  1571. fResult = FALSE;
  1572. nNumber = pfs->GetNumber(htv, fQL);
  1573. nFromHead = nFromTail = 0;
  1574. nToHead = nToTail = 0;
  1575. // intialize queues
  1576. phtiQueueTo = NULL;
  1577. phtiQueueFrom = new HTREEITEM[nNumber];
  1578. if (phtiQueueFrom == NULL)
  1579. goto Exit;
  1580. ZeroMemory(phtiQueueFrom, sizeof(HTREEITEM) * nNumber);
  1581. phtiQueueTo = new HTREEITEM[nNumber];
  1582. if (phtiQueueTo == NULL)
  1583. goto Exit;
  1584. ZeroMemory(phtiQueueTo, sizeof(HTREEITEM) * nNumber);
  1585. // put first element into the From queue, migrate it over
  1586. *(phtiQueueFrom + nFromTail++) = htiFrom;
  1587. ZeroMemory(&tvi, sizeof(tvi));
  1588. tvi.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE;
  1589. tvi.hItem = htiFrom;
  1590. TreeView_GetItem(htv, &tvi);
  1591. pfs = (LPFAVSTRUC)tvi.lParam;
  1592. if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1593. goto Exit;
  1594. tvi.mask |= TVIF_TEXT;
  1595. tvi.hItem = NULL;
  1596. tvi.pszText = pfs->pTvItem->pszText;
  1597. tvi.cchTextMax = StrLen(pfs->pTvItem->pszText) + 1;
  1598. if (*phtiAfter == TVI_FIRST || *phtiAfter == TVI_LAST)
  1599. htiParent = TreeView_GetParent(htv, htiFrom);
  1600. else
  1601. htiParent = TreeView_GetParent(htv, *phtiAfter);
  1602. ZeroMemory(&tvins, sizeof(tvins));
  1603. tvins.hParent = htiParent;
  1604. tvins.hInsertAfter = *phtiAfter;
  1605. CopyMemory(&tvins.item, &tvi, sizeof(tvi));
  1606. pfs->pTvItem->hItem = TreeView_InsertItem(htv, &tvins);
  1607. pfs->pTvItem->mask = TVIF_HANDLE | TVIF_STATE;
  1608. TreeView_GetItem(htv, pfs->pTvItem);
  1609. ZeroMemory(&tvi, sizeof(tvi));
  1610. tvi.mask = TVIF_PARAM;
  1611. tvi.hItem = htiFrom;
  1612. tvi.lParam = NULL;
  1613. TreeView_SetItem(htv, &tvi);
  1614. *(phtiQueueTo + nToTail++) = pfs->pTvItem->hItem;
  1615. // breadth-first graph traversion, non-recursive version
  1616. while (nFromHead < nFromTail) {
  1617. htiFromCur = *(phtiQueueFrom + nFromHead++);
  1618. htiToCur = *(phtiQueueTo + nToHead++);
  1619. ASSERT(htiFromCur != NULL && htiToCur != NULL);
  1620. for (htiChild = TreeView_GetChild(htv, htiFromCur);
  1621. htiChild != NULL;
  1622. htiChild = TreeView_GetNextSibling(htv, htiChild)) {
  1623. *(phtiQueueFrom + nFromTail++) = htiChild;
  1624. ASSERT(nFromTail < nNumber);
  1625. ZeroMemory(&tvi, sizeof(tvi));
  1626. tvi.mask = TVIF_CHILDREN | TVIF_PARAM | TVIF_SELECTEDIMAGE | TVIF_STATE;
  1627. tvi.hItem = htiChild;
  1628. TreeView_GetItem(htv, &tvi);
  1629. pfs = (LPFAVSTRUC)tvi.lParam;
  1630. if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1631. goto Exit;
  1632. tvi.mask |= TVIF_TEXT;
  1633. tvi.hItem = NULL;
  1634. tvi.pszText = pfs->pTvItem->pszText;
  1635. tvi.cchTextMax = StrLen(pfs->pTvItem->pszText) + 1;
  1636. ZeroMemory(&tvins, sizeof(tvins));
  1637. tvins.hParent = htiToCur;
  1638. tvins.hInsertAfter = TVI_LAST;
  1639. CopyMemory(&tvins.item, &tvi, sizeof(tvi));
  1640. pfs->pTvItem->hItem = TreeView_InsertItem(htv, &tvins);
  1641. pfs->pTvItem->mask = TVIF_HANDLE | TVIF_STATE;
  1642. TreeView_GetItem(htv, pfs->pTvItem);
  1643. ZeroMemory(&tvi, sizeof(tvi));
  1644. tvi.mask = TVIF_PARAM;
  1645. tvi.hItem = htiChild;
  1646. tvi.lParam = NULL;
  1647. TreeView_SetItem(htv, &tvi);
  1648. *(phtiQueueTo + nToTail++) = pfs->pTvItem->hItem;
  1649. ASSERT(nToTail < nNumber);
  1650. }
  1651. }
  1652. ASSERT(nFromHead == nFromTail && nToHead == nFromHead && nToHead == nToTail);
  1653. fResult = TRUE;
  1654. // NOTE: (andrewgu) nFromHead is used is a mere counter here.
  1655. for (nFromHead = 0; nFromHead < nNumber; nFromHead++) {
  1656. if (*(phtiQueueFrom + nFromHead) == NULL)
  1657. break;
  1658. ZeroMemory(&tvi, sizeof(tvi));
  1659. tvi.mask = TVIF_STATE;
  1660. tvi.hItem = *(phtiQueueFrom + nFromHead);
  1661. TreeView_GetItem(htv, &tvi);
  1662. if (HasFlag(tvi.state, TVIS_EXPANDED))
  1663. TreeView_Expand(htv, *(phtiQueueTo + nFromHead), TVE_EXPAND);
  1664. }
  1665. Exit:
  1666. *phtiAfter = fResult ? *phtiQueueTo : NULL;
  1667. delete[] phtiQueueFrom;
  1668. delete[] phtiQueueTo;
  1669. return fResult;
  1670. }
  1671. void importPath(HWND htv, HTREEITEM hti, LPCTSTR pszFilesPath, LPCTSTR pszExtractPath, LPCTSTR pszReserved /*= NULL*/)
  1672. {
  1673. static LPCTSTR s_pszBasePath;
  1674. static BOOL s_fMaxReached;
  1675. ISubscriptionMgr2 *psm;
  1676. WIN32_FIND_DATA fd;
  1677. LPFAVSTRUC pfs;
  1678. TCHAR szPath[MAX_PATH],
  1679. szLinksPath[MAX_PATH];
  1680. HANDLE hFindFile;
  1681. HRESULT hr;
  1682. BOOL fQL,
  1683. fIgnoreOffline;
  1684. //----- Setup globals -----
  1685. if (NULL == pszReserved) {
  1686. s_pszBasePath = pszFilesPath;
  1687. s_fMaxReached = FALSE;
  1688. }
  1689. if (s_fMaxReached)
  1690. return;
  1691. if (NULL == pszFilesPath)
  1692. return;
  1693. hr = isFavoriteItem(htv, hti);
  1694. if (FAILED(hr))
  1695. return;
  1696. fQL = (S_OK != hr);
  1697. szLinksPath[0] = TEXT('\0');
  1698. if (!fQL)
  1699. getLinksPath(szLinksPath);
  1700. fIgnoreOffline = FALSE;
  1701. psm = NULL;
  1702. hr = CoCreateInstance(CLSID_SubscriptionMgr, NULL, CLSCTX_INPROC_SERVER, IID_ISubscriptionMgr2, (LPVOID *)&psm);
  1703. if (FAILED(hr))
  1704. fIgnoreOffline = TRUE;
  1705. PathCombine(szPath, pszFilesPath, TEXT("*.*"));
  1706. hFindFile = FindFirstFile(szPath, &fd);
  1707. if (INVALID_HANDLE_VALUE == hFindFile)
  1708. return;
  1709. do {
  1710. PathCombine(szPath, pszFilesPath, fd.cFileName);
  1711. if (HasFlag(fd.dwFileAttributes, FILE_ATTRIBUTE_DIRECTORY)) {
  1712. // skip "." and ".." sub-directories
  1713. if (0 == StrCmp(fd.cFileName, TEXT(".")) || 0 == StrCmp(fd.cFileName, TEXT("..")))
  1714. continue;
  1715. // skip folders if importing under quick links
  1716. if (fQL)
  1717. continue;
  1718. // magic trick for quick links
  1719. if (0 == StrCmpI(szPath, szLinksPath)) {
  1720. pfs = pfs->GetFirst(htv, TRUE);
  1721. if (NULL == pfs || NULL == pfs->pTvItem || NULL == pfs->pTvItem->hItem)
  1722. continue;
  1723. importPath(htv, pfs->pTvItem->hItem, szPath, pszExtractPath, szPath);
  1724. continue;
  1725. }
  1726. importPath(htv, hti, szPath, pszExtractPath, s_pszBasePath);
  1727. }
  1728. else { /* it's a file */
  1729. // skip all file with extensions other than *.url
  1730. if (!PathIsExtension(fd.cFileName, DOT_URL))
  1731. continue;
  1732. if (NULL == pszReserved)
  1733. pszReserved = pszFilesPath;
  1734. ASSERT(StrLen(pszReserved) <= StrLen(pszFilesPath));
  1735. // determine if there is an object already for this
  1736. pfs = findByName(htv, hti, &szPath[StrLen(pszReserved) + 1]);
  1737. if (NULL != pfs) {
  1738. if (FTYPE_URL != pfs->wType ||
  1739. NULL == pfs->pTvItem || NULL == pfs->pTvItem->hItem)
  1740. break;
  1741. pfs->Free(htv, fQL, pszExtractPath);
  1742. }
  1743. pfs = pfs->CreateNew(htv, fQL);
  1744. if (NULL == pfs) {
  1745. if (pfs->GetNumber(htv, fQL) == pfs->GetMaxNumber(fQL)) {
  1746. ErrorMessageBox(GetParent(htv), IDS_FAV_ERR_NOTALL);
  1747. s_fMaxReached = TRUE;
  1748. }
  1749. break;
  1750. }
  1751. hr = pfs->Load(&szPath[StrLen(pszReserved) + (PathHasBackslash(pszReserved) ? 0 : 1)], szPath, pszExtractPath, psm, fIgnoreOffline);
  1752. if (FAILED(hr))
  1753. break;
  1754. pfs->Add(htv, hti);
  1755. }
  1756. } while (!s_fMaxReached && FindNextFile(hFindFile, &fd));
  1757. FindClose(hFindFile);
  1758. }
  1759. int exportItems(HWND htv, HTREEITEM hti, LPCTSTR pszIns, LPCTSTR pszExtractPath, BOOL fFixUpPath /*= TRUE */)
  1760. {
  1761. struct SVisited {
  1762. HTREEITEM hti;
  1763. BOOL fVisited;
  1764. } *pVisited;
  1765. LPFAVSTRUC pfs;
  1766. HTREEITEM htiCur, htiChild,
  1767. *phtiStack;
  1768. HRESULT hr;
  1769. UINT i, j, nNumber,
  1770. nStack;
  1771. BOOL fQL;
  1772. if (pszIns == NULL)
  1773. return -1;
  1774. hr = isFavoriteItem(htv, hti);
  1775. if (FAILED(hr))
  1776. return -1;
  1777. fQL = (hr != S_OK);
  1778. pfs = getFolderItem(htv, hti);
  1779. if (pfs == NULL || pfs->pTvItem == NULL || pfs->pTvItem->hItem == NULL)
  1780. return -1;
  1781. nNumber = pfs->GetNumber(htv, fQL);
  1782. nStack = 0;
  1783. // intialize stack
  1784. phtiStack = new HTREEITEM[nNumber];
  1785. if (phtiStack == NULL)
  1786. return -1;
  1787. ZeroMemory(phtiStack, sizeof(HTREEITEM) * nNumber);
  1788. *phtiStack = pfs->pTvItem->hItem;
  1789. nStack++;
  1790. // initialize visited array
  1791. pVisited = new SVisited[nNumber];
  1792. if (pVisited == NULL)
  1793. {
  1794. delete [] phtiStack;
  1795. return -1;
  1796. }
  1797. for (i = 0; pfs != NULL; i++, pfs = pfs->GetNext(htv, fQL)) {
  1798. (pVisited + i)->hti = (pfs->pTvItem != NULL && pfs->pTvItem->hItem != NULL) ? pfs->pTvItem->hItem : NULL;
  1799. (pVisited + i)->fVisited = FALSE;
  1800. }
  1801. ASSERT(i == nNumber);
  1802. // mark root as visited
  1803. for (i = 0; i < nNumber; i++)
  1804. if ((pVisited + i)->hti == *phtiStack)
  1805. break;
  1806. ASSERT(i < nNumber);
  1807. (pVisited + i)->fVisited = TRUE;
  1808. for (j = 1; nStack > 0; ) {
  1809. htiCur = *(phtiStack + nStack-1);
  1810. // determine if there are non-visited children
  1811. for (htiChild = TreeView_GetChild(htv, htiCur);
  1812. htiChild != NULL;
  1813. htiChild = TreeView_GetNextSibling(htv, htiChild)) {
  1814. for (i = 0; i < nNumber; i++)
  1815. if ((pVisited + i)->hti == htiChild)
  1816. break;
  1817. if (i < nNumber && !(pVisited + i)->fVisited)
  1818. break;
  1819. }
  1820. if (htiChild != NULL) {
  1821. // add non-visited child to the stack
  1822. *(phtiStack + nStack) = htiChild;
  1823. nStack++;
  1824. ASSERT((pVisited + i)->hti == htiChild);
  1825. (pVisited + i)->fVisited = TRUE;
  1826. pfs = getItem(htv, htiChild);
  1827. if (pfs == NULL || pfs->wType != FTYPE_URL)
  1828. continue;
  1829. pfs->Save(htv, j++, pszIns, pszExtractPath, fQL, fFixUpPath);
  1830. }
  1831. else
  1832. // all visited -> pop
  1833. *(phtiStack + --nStack) = NULL;
  1834. }
  1835. delete[] phtiStack;
  1836. delete[] pVisited;
  1837. return j;
  1838. }
  1839. BOOL extractIcon(LPCTSTR pszIconFile, int iIconIndex, LPCTSTR pszExtractPath, LPTSTR pszResult, UINT cchResult)
  1840. {
  1841. TCHAR szExtractedFile[MAX_PATH];
  1842. HRESULT hr;
  1843. UINT i;
  1844. BOOL fURL;
  1845. if (pszIconFile == NULL || pszExtractPath == NULL || pszResult == NULL)
  1846. return FALSE;
  1847. *pszResult = TEXT('\0');
  1848. if (cchResult == 0)
  1849. cchResult = MAX_PATH;
  1850. fURL = PathIsURL(pszIconFile);
  1851. if (fURL) {
  1852. PathCombine(szExtractedFile, pszExtractPath, PathFindFileName(pszIconFile));
  1853. hr = URLDownloadToFile(NULL, pszIconFile, szExtractedFile, 0L, NULL);
  1854. if (FAILED(hr))
  1855. return FALSE;
  1856. }
  1857. else {
  1858. static LPCTSTR rgpszCopyExt[] = {
  1859. DOT_ICO,
  1860. DOT_URL
  1861. };
  1862. static LPCTSTR rgpszExtractExt[] = {
  1863. DOT_EXE,
  1864. DOT_DLL
  1865. };
  1866. IStream *pStm;
  1867. IPicture *pPic;
  1868. PICTDESC pd;
  1869. LPCTSTR pszExt;
  1870. LPVOID pIcon;
  1871. HANDLE hFile;
  1872. HGLOBAL hmem;
  1873. HICON hicon;
  1874. HRESULT hr;
  1875. DWORD dwWritten;
  1876. LONG cbIcon;
  1877. // if it's an icon file just copy it
  1878. pszExt = PathFindExtension(pszIconFile);
  1879. for (i = 0; i < countof(rgpszCopyExt); i++)
  1880. if (StrCmpI(pszExt, rgpszCopyExt[i]) == 0)
  1881. break;
  1882. if (i < countof(rgpszCopyExt)) {
  1883. StrCpy(szExtractedFile, pszIconFile);
  1884. goto Exit;
  1885. }
  1886. // if it doesn't have extension from which icon can be extracted bail out
  1887. for (i = 0; i < countof(rgpszExtractExt); i++)
  1888. if (StrCmpI(pszExt, rgpszExtractExt[i]) == 0)
  1889. break;
  1890. if (i >= countof(rgpszExtractExt))
  1891. return FALSE;
  1892. // extract icons
  1893. ExtractIconEx(pszIconFile, iIconIndex, &hicon, NULL, 1);
  1894. if (hicon == NULL)
  1895. return FALSE;
  1896. hr = CreateStreamOnHGlobal(NULL, TRUE, &pStm);
  1897. if (FAILED(hr)) {
  1898. DestroyIcon(hicon);
  1899. return FALSE;
  1900. }
  1901. ZeroMemory(&pd, sizeof(pd));
  1902. pd.cbSizeofstruct = sizeof(pd);
  1903. pd.picType = PICTYPE_ICON;
  1904. pd.icon.hicon = hicon;
  1905. hr = OleCreatePictureIndirect(&pd, IID_IPicture, TRUE, (LPVOID *)&pPic);
  1906. if (FAILED(hr)) {
  1907. DestroyIcon(hicon);
  1908. return FALSE;
  1909. }
  1910. hr = pPic->SaveAsFile(pStm, TRUE, &cbIcon);
  1911. pPic->Release();
  1912. if (FAILED(hr)) {
  1913. pStm->Release();
  1914. return FALSE;
  1915. }
  1916. // generate a unique icon name
  1917. do {
  1918. GetTempFileName(pszExtractPath, PREFIX_ICON, 0, szExtractedFile);
  1919. DeleteFile(szExtractedFile);
  1920. PathRenameExtension(szExtractedFile, DOT_ICO);
  1921. } while (PathFileExists(szExtractedFile));
  1922. hFile = CreateFile(szExtractedFile, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
  1923. if (hFile == INVALID_HANDLE_VALUE) {
  1924. pStm->Release();
  1925. return FALSE;
  1926. }
  1927. GetHGlobalFromStream(pStm, &hmem);
  1928. ASSERT(hmem != NULL);
  1929. pIcon = GlobalLock(hmem);
  1930. ASSERT(pIcon != NULL);
  1931. WriteFile(hFile, pIcon, cbIcon, &dwWritten, NULL);
  1932. CloseHandle(hFile);
  1933. GlobalUnlock(hmem);
  1934. pStm->Release();
  1935. }
  1936. Exit:
  1937. if (cchResult <= (UINT)StrLen(szExtractedFile))
  1938. return FALSE;
  1939. StrCpy(pszResult, szExtractedFile);
  1940. return TRUE;
  1941. }
  1942. LPCTSTR getLinksPath(LPTSTR pszPath, UINT cchPath /*= 0*/)
  1943. {
  1944. LPITEMIDLIST pidl;
  1945. TCHAR szPath[MAX_PATH],
  1946. szLinks[MAX_PATH];
  1947. HRESULT hr;
  1948. if (pszPath != NULL)
  1949. *pszPath = TEXT('\0');
  1950. if (cchPath == 0)
  1951. cchPath = MAX_PATH;
  1952. hr = SHGetSpecialFolderLocation(NULL, CSIDL_FAVORITES, &pidl);
  1953. if (FAILED(hr))
  1954. return NULL;
  1955. hr = SHGetPathFromIDList(pidl, szPath) ? S_OK : E_FAIL;
  1956. CoTaskMemFree(pidl);
  1957. if (FAILED(hr))
  1958. return NULL;
  1959. ASSERT(szPath[0] != TEXT('\0'));
  1960. szLinks[0] = TEXT('\0');
  1961. LoadString(g_hInst, IDS_LINKS, szLinks, countof(szLinks));
  1962. if (szLinks[0] == TEXT('\0'))
  1963. return NULL;
  1964. PathAppend(szPath, szLinks);
  1965. if (cchPath <= (UINT)StrLen(szPath))
  1966. return NULL;
  1967. StrCpy(pszPath, szPath);
  1968. return pszPath;
  1969. }
  1970. LPTSTR encodeFavName(LPTSTR pszFavName, LPCTSTR pszIns)
  1971. {
  1972. TCHAR szWrk[MAX_PATH],
  1973. chWrk;
  1974. LPTSTR pszFrom;
  1975. LPTSTR pszTo;
  1976. BOOL fEncodeFavs;
  1977. StrCpy(szWrk, pszFavName);
  1978. pszFrom = szWrk;
  1979. pszTo = pszFavName;
  1980. fEncodeFavs = FALSE;
  1981. while (*pszFrom != TEXT('\0')) {
  1982. switch(chWrk = *pszFrom++) {
  1983. case TEXT('['):
  1984. fEncodeFavs = TRUE;
  1985. *pszTo++ = TEXT('%');
  1986. *pszTo++ = TEXT('(');
  1987. break;
  1988. case TEXT(']'):
  1989. fEncodeFavs = TRUE;
  1990. *pszTo++ = TEXT('%');
  1991. *pszTo++ = TEXT(')');
  1992. break;
  1993. case TEXT('='):
  1994. fEncodeFavs = TRUE;
  1995. *pszTo++ = TEXT('%');
  1996. *pszTo++ = TEXT('-');
  1997. break;
  1998. case TEXT('%'):
  1999. fEncodeFavs = TRUE;
  2000. *pszTo++ = TEXT('%');
  2001. *pszTo++ = TEXT('%');
  2002. break;
  2003. default:
  2004. *pszTo++ = chWrk;
  2005. break;
  2006. }
  2007. }
  2008. *pszTo = TEXT('\0');
  2009. InsWriteBool(IS_BRANDING, IK_FAVORITES_ENCODE, fEncodeFavs, pszIns);
  2010. return pszFavName;
  2011. }
  2012. LPTSTR decodeFavName(LPTSTR pszFavName, LPCTSTR pszIns)
  2013. {
  2014. TCHAR szWrk[MAX_PATH],
  2015. chWrk;
  2016. LPTSTR pszFrom;
  2017. LPTSTR pszTo;
  2018. if (!InsGetBool(IS_BRANDING, IK_FAVORITES_ENCODE, FALSE, pszIns))
  2019. return pszFavName;
  2020. StrCpy(szWrk, pszFavName);
  2021. pszFrom = szWrk;
  2022. pszTo = pszFavName;
  2023. while((*pszFrom != TEXT('\0')) && ((chWrk = *pszFrom++) != TEXT('\0'))) {
  2024. if (chWrk != TEXT('%'))
  2025. *pszTo++ = chWrk;
  2026. else {
  2027. switch(chWrk = *pszFrom++) {
  2028. case TEXT('('): *pszTo++ = TEXT('['); break;
  2029. case TEXT(')'): *pszTo++ = TEXT(']'); break;
  2030. case TEXT('-'): *pszTo++ = TEXT('='); break;
  2031. case TEXT('%'): *pszTo++ = TEXT('%'); break;
  2032. case TEXT('/'):
  2033. #ifndef _UNICODE
  2034. *pszTo++ = IsDBCSLeadByte(*(pszTo - 1)) ? TEXT('\\') : TEXT('/');
  2035. #else
  2036. *pszTo++ = TEXT('/');
  2037. #endif
  2038. break;
  2039. default:
  2040. *pszTo++ = TEXT('%');
  2041. *pszTo++ = chWrk;
  2042. break;
  2043. }
  2044. }
  2045. }
  2046. *pszTo = TEXT('\0');
  2047. return pszFavName;
  2048. }