Source code of Windows XP (NT5)
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.

2700 lines
75 KiB

  1. /*
  2. * Author: t-franks
  3. *
  4. * Last Modified On: Oct 16, 1998
  5. * Last Modified By: t-joshp
  6. *
  7. */
  8. #include "priv.h"
  9. #include "resource.h"
  10. #include "impexp.h"
  11. #include "mluisupp.h" // for MLLoadString
  12. #include "apithk.h"
  13. //
  14. // Indices into our imagelist
  15. // (used for the open and closed folder icons on the tree view)
  16. //
  17. #define FOLDER_CLOSED 0
  18. #define FOLDER_OPEN 1
  19. #define ImportCookieFile ImportCookieFileW
  20. #define ExportCookieFile ExportCookieFileW
  21. BOOL ImportCookieFileW(IN LPCWSTR szFilename);
  22. BOOL ExportCookieFileW(IN LPCWSTR szFilename, BOOL fAppend);
  23. extern void SetListViewToString (HWND hLV, LPCTSTR pszString);
  24. //
  25. // used to display "file already exists" and "file not found" messages
  26. //
  27. int WarningMessageBox(HWND hwnd, UINT idTitle, UINT idMessage, LPCTSTR szFile, DWORD dwFlags);
  28. //
  29. // Strings that don't need localizing
  30. //
  31. #define NS3_COOKIE_REG_PATH TEXT("Software\\Netscape\\Netscape Navigator\\Cookies")
  32. #define NS3_COOKIE_REG_KEY TEXT("Cookie File")
  33. #ifndef UNIX
  34. #define NS3_BOOKMARK_REG_PATH TEXT("Software\\Netscape\\Netscape Navigator\\Bookmark List")
  35. #else
  36. #define NS3_BOOKMARK_REG_PATH TEXT("SOFTWARE\\Microsoft\\Internet Explorer\\unix\\nsbookmarks")
  37. #endif
  38. #define NS3_BOOKMARK_REG_KEY TEXT("File Location")
  39. #define NS4_USERS_REG_PATH TEXT("Software\\Netscape\\Netscape Navigator\\Users")
  40. #define NS4_USERPATH_REG_KEY TEXT("DirRoot")
  41. #define NS_FALLBACK_ROOT_REG_KEY TEXT("Software\\Netscape\\Netscape Navigator")
  42. #define NS_FALLBACK_VERSION_REG_VAL TEXT("CurrentVersion")
  43. #define NS_FALLBACK_MAIN_REG_VAL TEXT("Main")
  44. #define NS_FALLBACK_INST_REG_VAL TEXT("Install Directory")
  45. #ifndef UNIX
  46. #define ALL_FILES_WILDCARD TEXT("\\*.*")
  47. #else
  48. #define ALL_FILES_WILDCARD TEXT("/*")
  49. #endif
  50. #define DOT_DIR TEXT(".")
  51. #define DOT_DOT_DIR TEXT("..")
  52. #ifdef UNIX
  53. #define DIR_SEPARATOR_CHAR TEXT('/')
  54. #else
  55. #define DIR_SEPARATOR_CHAR TEXT('\\')
  56. #endif
  57. //*************************************************************
  58. //
  59. // class ListIterator
  60. //
  61. // Keeps hold on a position in a list. Allows basic access
  62. //to a list. The list is set up to map a name to a value.
  63. class NestedList;
  64. class ListIterator
  65. {
  66. friend NestedList;
  67. struct node
  68. {
  69. LPTSTR _sName;
  70. LPTSTR _sValue;
  71. DWORD _cNameSize, _cValueSize;
  72. node* _pnNext;
  73. node* _pnSublist;
  74. };
  75. // A position is held by pointing to the
  76. //current node and the pointer that is directed
  77. //to that node. The back pointer is kept so the
  78. //list can be manipulated at the current element.
  79. // when m_pnCurrent == NULL, the iterator is
  80. //at the end of the list.
  81. node** m_ppnPrev;
  82. node* m_pnCurrent;
  83. // The invariant could be broken if two iterators
  84. //point to the same node, and one inserts or deletes
  85. //an element. So only one iterator should exist in
  86. //a branch of the list at a time.
  87. BOOL invariant()
  88. {
  89. return *m_ppnPrev == m_pnCurrent;
  90. }
  91. public:
  92. ListIterator( node** ppnPrev)
  93. {
  94. m_ppnPrev = ppnPrev;
  95. m_pnCurrent = *m_ppnPrev;
  96. }
  97. BOOL Insert( LPCTSTR sName, DWORD cNameSize, LPCTSTR sValue, DWORD cValueSize);
  98. BOOL Remove();
  99. ListIterator GetSublist();
  100. void DeleteSublist();
  101. BOOL Next();
  102. BOOL AtEndOfList();
  103. LPCTSTR GetName();
  104. DWORD GetNameSize();
  105. LPCTSTR GetValue();
  106. DWORD GetValueSize();
  107. };
  108. //*************************************************************
  109. //
  110. // class NestedList
  111. // Keeps a pointer to a node which heads a list,
  112. // and deletes that list on destruction.
  113. class NestedList
  114. {
  115. ListIterator::node* m_pnRoot;
  116. public:
  117. NestedList();
  118. ~NestedList();
  119. operator ListIterator();
  120. };
  121. NestedList::NestedList()
  122. : m_pnRoot(NULL)
  123. {
  124. }
  125. NestedList::~NestedList()
  126. {
  127. while( ((ListIterator)*this).Remove())
  128. {
  129. }
  130. }
  131. NestedList::operator ListIterator()
  132. {
  133. return ListIterator( &m_pnRoot);
  134. }
  135. //*************************************************************
  136. //*************************************************************
  137. //
  138. // ListIterator functions
  139. //
  140. // Inserts an element before the current one,
  141. //leaves iterator pointing at new node.
  142. BOOL ListIterator::Insert(
  143. LPCTSTR sName,
  144. DWORD cNameSize,
  145. LPCTSTR sValue,
  146. DWORD cValueSize)
  147. {
  148. ASSERT( invariant());
  149. node* pNewNode = (node*)(new BYTE[ sizeof(node)
  150. + (( cNameSize + cValueSize)
  151. * sizeof(TCHAR))]);
  152. if( pNewNode == NULL)
  153. return FALSE;
  154. // the name and value will be appended to the node.
  155. pNewNode->_sName = (LPTSTR)((BYTE*)pNewNode + sizeof(node));
  156. pNewNode->_sValue = pNewNode->_sName + cNameSize;
  157. pNewNode->_cNameSize = cNameSize;
  158. pNewNode->_cValueSize = cValueSize;
  159. memcpy( pNewNode->_sName, sName, pNewNode->_cNameSize * sizeof(TCHAR));
  160. memcpy( pNewNode->_sValue, sValue, pNewNode->_cValueSize * sizeof(TCHAR));
  161. // insert new node in list
  162. pNewNode->_pnNext = m_pnCurrent;
  163. *m_ppnPrev = pNewNode;
  164. // The iterator now points to the new element.
  165. m_pnCurrent = *m_ppnPrev;
  166. ASSERT( invariant());
  167. return TRUE;
  168. }
  169. // Deletes the current node.
  170. // Returns FALSE if at end of list.
  171. BOOL ListIterator::Remove()
  172. {
  173. ASSERT( invariant());
  174. // If this list is empty, or if the iterator
  175. //points at the end of the list, there is nothing to
  176. //delete.
  177. if( m_pnCurrent == NULL)
  178. return FALSE;
  179. // remove sublist
  180. DeleteSublist();
  181. // Remember where target node is
  182. //so it can be deleted once out of
  183. //the list.
  184. node* pOldNode = m_pnCurrent;
  185. // take the target node out of the list.
  186. //(iterator points to next node or end of list)
  187. *m_ppnPrev = m_pnCurrent->_pnNext;
  188. m_pnCurrent = *m_ppnPrev;
  189. // Get rid of target node.
  190. delete [] (BYTE*)pOldNode;
  191. ASSERT( invariant());
  192. return TRUE;
  193. }
  194. // Returns the sublist of the current node.
  195. ListIterator ListIterator::GetSublist()
  196. {
  197. ASSERT( invariant());
  198. return ListIterator( &(m_pnCurrent->_pnSublist));
  199. }
  200. // deletes the children of the current node.
  201. void ListIterator::DeleteSublist()
  202. {
  203. ASSERT( invariant());
  204. ListIterator sublist( &(m_pnCurrent->_pnSublist));
  205. while( sublist.Remove())
  206. {
  207. }
  208. ASSERT( invariant());
  209. }
  210. // Advances to the next node.
  211. // Returns FALSE if already at end of list.
  212. BOOL ListIterator::Next()
  213. {
  214. ASSERT( invariant());
  215. if( m_pnCurrent == NULL)
  216. return FALSE;
  217. m_ppnPrev = &(m_pnCurrent->_pnNext);
  218. m_pnCurrent = *m_ppnPrev;
  219. ASSERT( invariant());
  220. return m_pnCurrent != NULL;
  221. }
  222. //
  223. BOOL ListIterator::AtEndOfList()
  224. {
  225. return ( m_pnCurrent == NULL) ? TRUE : FALSE;
  226. };
  227. //
  228. LPCTSTR ListIterator::GetName()
  229. {
  230. ASSERT( invariant() && m_pnCurrent != NULL);
  231. return m_pnCurrent->_sName;
  232. }
  233. //
  234. DWORD ListIterator::GetNameSize()
  235. {
  236. ASSERT( invariant() && m_pnCurrent != NULL);
  237. return m_pnCurrent->_cNameSize;
  238. }
  239. //
  240. LPCTSTR ListIterator::GetValue()
  241. {
  242. ASSERT( invariant() && m_pnCurrent != NULL);
  243. return m_pnCurrent->_sValue;
  244. }
  245. //
  246. DWORD ListIterator::GetValueSize()
  247. {
  248. ASSERT( invariant() && m_pnCurrent != NULL);
  249. return m_pnCurrent->_cValueSize;
  250. }
  251. //*************************************************************
  252. //*************************************************************
  253. //
  254. // class ImpExpUserProcess
  255. //
  256. // maintains the description of an import/export process
  257. // for an import/export wizard, and finally executes the
  258. // the import/export.
  259. enum ExternalType { INVALID_EXTERNAL = 0, COOKIES, BOOKMARKS};
  260. enum TransferType { INVALID_TRANSFER = 0, IMPORT, EXPORT};
  261. class ImpExpUserProcess
  262. {
  263. public:
  264. ImpExpUserProcess();
  265. ~ImpExpUserProcess();
  266. // the first step the wizard should do is identify the type of
  267. //import/export process to be done.
  268. void SelectExternalType( ExternalType selection) { m_ExternalType = selection; }
  269. void SelectTransferType( TransferType selection) { m_TransferType = selection; }
  270. ExternalType GetExternalType() { return m_ExternalType; }
  271. TransferType GetTransferType() { return m_TransferType; }
  272. BOOL PopulateComboBoxForExternalSelection( HWND hComboBox);
  273. BOOL GetExternalManualDefault( LPTSTR sExternal, DWORD* pcSize);
  274. //
  275. // used to fill the listbox with names of netscape profiles
  276. //
  277. void purgeExternalList();
  278. BOOL populateExternalList();
  279. BOOL populateExternalListForCookiesOrBookmarks();
  280. //
  281. // for netscape 3.x
  282. //
  283. BOOL populateExternalListForCookiesOrBookmarksWithNS3Entry();
  284. //
  285. // for netscape 4.x
  286. //
  287. BOOL populateExternalListForCookiesOrBookmarksWithNS4Entries();
  288. //
  289. // fallback case for "funny" versions of netscape
  290. //
  291. BOOL populateExternalListFromFolders(LPTSTR pszPath);
  292. BOOL populateExternalListWithNSEntriesFallBack();
  293. // If the transfer is for favorites, the wizard needs to specify
  294. //an internal folder to import to or export from.
  295. LPCTSTR GetInternalSelection() { return m_pSelectedInternal; }
  296. BOOL PopulateTreeViewForInternalSelection( HWND TreeView);
  297. BOOL populateTreeViewWithInternalList( HWND hTreeView, ListIterator iterator, HTREEITEM hParent);
  298. BOOL ExpandTreeViewRoot ( HWND hTreeView ) ;
  299. BOOL SelectInternalSelection( HWND TreeView);
  300. void purgeInternalList();
  301. BOOL populateInternalList();
  302. BOOL populateInternalListForBookmarks();
  303. BOOL appendSubdirsToInternalList( LPTSTR sPath, ListIterator iterator);
  304. // And then, the import/export can be completed.
  305. void PerformImpExpProcess(HWND hwnd);
  306. //
  307. // The filename that we're exporting to or
  308. // importing from.
  309. //
  310. TCHAR m_szFileName[MAX_PATH];
  311. private:
  312. ExternalType m_ExternalType;
  313. TransferType m_TransferType;
  314. // m_ExternalList is a flat list of names associated with files
  315. //example: name = "Netscape 4.0 profile - Dr. Falken"
  316. // value = "c:\netscapeprofiledir\DrFalken.chs"
  317. NestedList m_ExternalList;
  318. // m_InternalList is a nested list favorites' pathnames,
  319. //associated with the complete path.
  320. NestedList m_InternalList;
  321. // Maintain synchronization between m_ExternalType/m_TransferType
  322. //and m_InternalList
  323. ExternalType m_InternalListExternalType;
  324. TransferType m_InternalListTransferType;
  325. // if ExternalType == BOOKMARKS,
  326. //m_pSelectedInternal is the path of a Favorites folder,
  327. //residing in m_InternalList somewhere, or NULL if a folder
  328. //hasn't been selected yet.
  329. LPTSTR m_pSelectedInternal;
  330. };
  331. ImpExpUserProcess::ImpExpUserProcess()
  332. : m_ExternalType(INVALID_EXTERNAL), m_TransferType(INVALID_TRANSFER),
  333. m_InternalListExternalType(INVALID_EXTERNAL), m_InternalListTransferType(INVALID_TRANSFER),
  334. m_pSelectedInternal(0)
  335. {
  336. }
  337. ImpExpUserProcess::~ImpExpUserProcess()
  338. {
  339. }
  340. //*************************************************************
  341. // PopulateComboBoxForExternal
  342. //
  343. // Loads content for list box into memory and into List Box,
  344. //associating value of each element with the list element.
  345. // returns FALSE if the list box is left empty
  346. BOOL ImpExpUserProcess::PopulateComboBoxForExternalSelection( HWND hComboBox)
  347. {
  348. ASSERT ( m_ExternalType != INVALID_EXTERNAL ) ;
  349. ComboBox_ResetContent(hComboBox);
  350. // If ExternalList is invalid, the list box will be left empty.
  351. if( !populateExternalList() )
  352. return FALSE;
  353. ListIterator iterator = m_ExternalList;
  354. // Detect and notify if the list is empty.
  355. if( iterator.AtEndOfList() )
  356. return FALSE;
  357. // add entries from the new ExternalList to the ComboBox.
  358. do
  359. {
  360. int index = ComboBox_AddString( hComboBox, const_cast<LPTSTR>(iterator.GetName() ) );
  361. ComboBox_SetItemData( hComboBox, index, const_cast<LPTSTR>(iterator.GetValue() ) );
  362. } while( iterator.Next());
  363. // set the first one as selected
  364. ComboBox_SetCurSel( hComboBox, 0 );
  365. return TRUE;
  366. }
  367. //*************************************************************
  368. //
  369. // GetExternalManualDefault
  370. //
  371. // Allows user interface to offer some sort of default
  372. // filename/location.
  373. //
  374. BOOL ImpExpUserProcess::GetExternalManualDefault(LPTSTR sExternal, DWORD* pcSize)
  375. {
  376. ASSERT(NULL != pcSize);
  377. //
  378. // We only fill it in if it's blank
  379. //
  380. if (m_szFileName[0])
  381. {
  382. return FALSE;
  383. }
  384. ListIterator iterator = m_ExternalList;
  385. TCHAR szFileName[MAX_PATH];
  386. INT cchFileName;
  387. if(m_ExternalType == BOOKMARKS)
  388. MLLoadString(IDS_NETSCAPE_BOOKMARK_FILE,szFileName,ARRAYSIZE(szFileName));
  389. else
  390. MLLoadString(IDS_NETSCAPE_COOKIE_FILE,szFileName,ARRAYSIZE(szFileName));
  391. cchFileName = lstrlen(szFileName) + 1;
  392. // Grab the first item in the External List and use its value.
  393. if( ((ListIterator)m_ExternalList).AtEndOfList() == FALSE
  394. && ((ListIterator)m_ExternalList).GetValue() != NULL
  395. && *pcSize >= ((ListIterator)m_ExternalList).GetValueSize())
  396. {
  397. StrCpyN( sExternal,
  398. ((ListIterator)m_ExternalList).GetValue(),
  399. ((ListIterator)m_ExternalList).GetValueSize());
  400. *pcSize = ((ListIterator)m_ExternalList).GetValueSize();
  401. return TRUE;
  402. }
  403. // If there is enough room, specify some file with the correct name
  404. // in the "my documents" directory.
  405. else
  406. {
  407. ASSERT(m_ExternalType == BOOKMARKS || m_ExternalType == COOKIES);
  408. TCHAR szMyDocsPath[MAX_PATH];
  409. SHGetSpecialFolderPath(NULL,szMyDocsPath,CSIDL_PERSONAL,TRUE);
  410. *pcSize = wnsprintf(sExternal,MAX_PATH,TEXT("%s%c%s"),szMyDocsPath,DIR_SEPARATOR_CHAR,szFileName);
  411. return *pcSize > 0;
  412. }
  413. }
  414. //*************************************************************
  415. //
  416. //
  417. // purgeExternalList
  418. //
  419. // Used to clear external target/source list loaded into memory
  420. void ImpExpUserProcess::purgeExternalList()
  421. {
  422. // delete elements until they're all gone.
  423. ListIterator iterator = m_ExternalList;
  424. while( iterator.Remove())
  425. {
  426. }
  427. }
  428. //*************************************************************
  429. //
  430. // populeExternalList
  431. //
  432. // Used to load external target/source list into memory
  433. BOOL ImpExpUserProcess::populateExternalList()
  434. {
  435. ASSERT(m_ExternalType != INVALID_EXTERNAL)
  436. purgeExternalList();
  437. if(!populateExternalListForCookiesOrBookmarks())
  438. {
  439. //
  440. // If we didn't get any entries using the "standard"
  441. // techniques, then (and only then) we try the "fallback"
  442. //
  443. if (!populateExternalListWithNSEntriesFallBack())
  444. {
  445. purgeExternalList();
  446. return FALSE;
  447. }
  448. }
  449. return TRUE;
  450. }
  451. //*************************************************************
  452. //
  453. // populateExternalListforCookiesOrBookmarks
  454. //
  455. // Used to lod external target/source list into memory
  456. //in the case that the content to be transfered is cookies
  457. //or bookmarks.
  458. // returns TRUE if any elements have been added to the external list
  459. BOOL ImpExpUserProcess::populateExternalListForCookiesOrBookmarks()
  460. {
  461. ASSERT( m_ExternalType == COOKIES || m_ExternalType == BOOKMARKS);
  462. BOOL fHasAddedElements = FALSE;
  463. if( populateExternalListForCookiesOrBookmarksWithNS3Entry())
  464. fHasAddedElements = TRUE;
  465. if( populateExternalListForCookiesOrBookmarksWithNS4Entries())
  466. fHasAddedElements = TRUE;
  467. return fHasAddedElements;
  468. }
  469. //*************************************************************
  470. //
  471. // populateExternalList..WithNS3Entry
  472. //
  473. // subfunc of populateExternalListForCookiesOrBookmarks.
  474. // returns TRUE if any elements have been added to the external list
  475. BOOL ImpExpUserProcess::populateExternalListForCookiesOrBookmarksWithNS3Entry()
  476. {
  477. BOOL retVal = FALSE;
  478. // Determine where to look for reg key
  479. LPTSTR sNS3RegPath;
  480. LPTSTR sNS3RegKey;
  481. if( m_ExternalType == BOOKMARKS)
  482. {
  483. sNS3RegPath = NS3_BOOKMARK_REG_PATH;
  484. sNS3RegKey = NS3_BOOKMARK_REG_KEY;
  485. }
  486. else
  487. {
  488. sNS3RegPath = NS3_COOKIE_REG_PATH;
  489. sNS3RegKey = NS3_COOKIE_REG_KEY;
  490. }
  491. // Get the file location and add it to the list
  492. // The registry location has the complete path + filename.
  493. TCHAR sFilePath[MAX_PATH];
  494. DWORD cbFilePathSize = sizeof(sFilePath);
  495. DWORD dwType;
  496. if (ERROR_SUCCESS == SHGetValue(HKEY_CURRENT_USER, sNS3RegPath, sNS3RegKey,
  497. &dwType, (BYTE*)sFilePath, &cbFilePathSize)
  498. && (dwType == REG_SZ || dwType == REG_EXPAND_SZ))
  499. {
  500. TCHAR szBuffer[MAX_PATH];
  501. MLLoadString(IDS_NS3_VERSION_CAPTION, szBuffer, MAX_PATH);
  502. retVal = ((ListIterator)m_ExternalList).Insert(
  503. szBuffer, lstrlen(szBuffer)+1,
  504. sFilePath, cbFilePathSize / sizeof(TCHAR));
  505. }
  506. return retVal;
  507. }
  508. //*************************************************************
  509. //
  510. // populateExternalList..WithNS4Entries
  511. //
  512. // subfunc of populateExternalListForCookiesOrBookmarks.
  513. // returns TRUE if any elements have been added to the external list
  514. BOOL ImpExpUserProcess::populateExternalListForCookiesOrBookmarksWithNS4Entries()
  515. {
  516. BOOL retVal = FALSE;
  517. // Get an iterator to advance position as items are inserted.
  518. ListIterator iterator = (ListIterator)m_ExternalList;
  519. // Get the filename to be attached and the associated string size.
  520. TCHAR sFilename[MAX_PATH];
  521. DWORD cFilenameLength;
  522. if(m_ExternalType == BOOKMARKS)
  523. MLLoadString(IDS_NETSCAPE_BOOKMARK_FILE,sFilename,ARRAYSIZE(sFilename));
  524. else
  525. MLLoadString(IDS_NETSCAPE_COOKIE_FILE,sFilename,ARRAYSIZE(sFilename));
  526. cFilenameLength = lstrlen(sFilename);
  527. // Get the reg key of the root of the NS profiles for enumeration.
  528. HKEY hUserRootKey = NULL;
  529. if( RegOpenKeyEx( HKEY_LOCAL_MACHINE, NS4_USERS_REG_PATH,
  530. 0, KEY_READ, &hUserRootKey)
  531. != ERROR_SUCCESS)
  532. {
  533. hUserRootKey = NULL;
  534. goto donePopulateExternalListForCookiesOrBookmarksWithNS4Entries;
  535. }
  536. DWORD dwNumberOfProfiles;
  537. if( RegQueryInfoKey( hUserRootKey, NULL, NULL, NULL, &dwNumberOfProfiles,
  538. NULL, NULL, NULL, NULL, NULL, NULL, NULL) != ERROR_SUCCESS
  539. || dwNumberOfProfiles == 0)
  540. {
  541. goto donePopulateExternalListForCookiesOrBookmarksWithNS4Entries;
  542. }
  543. // Enumerate over the NS profiles, getting their names and
  544. //directory paths. Associated the profile name with the path
  545. //of the desired files by appending the filename to the
  546. //user's root.
  547. TCHAR sProfileName[MAX_PATH];
  548. DWORD cProfileNameSize;
  549. cProfileNameSize = MAX_PATH;
  550. DWORD iEnumIndex; iEnumIndex = 0;
  551. while( RegEnumKeyEx( hUserRootKey, (iEnumIndex++), sProfileName,
  552. &cProfileNameSize, NULL, NULL, NULL, NULL)
  553. == ERROR_SUCCESS)
  554. {
  555. //RegEnumKeyEx gives us the ProfileNameSize w/out the '\0'.
  556. cProfileNameSize = MAX_PATH;
  557. HKEY hProfileKey = NULL;
  558. if( RegOpenKeyEx( hUserRootKey, sProfileName, 0, KEY_READ, &hProfileKey)
  559. != ERROR_SUCCESS)
  560. {
  561. hProfileKey = NULL;
  562. goto doneWithEntryInPopulateExternalListForCookiesOrBookmarksWithNS4Entries;
  563. }
  564. DWORD dwType; // should be REG_SZ when returned from QueryValue
  565. TCHAR sProfilePath[MAX_PATH];
  566. DWORD cProfilePathSize; cProfilePathSize = sizeof(sProfilePath);
  567. if( (RegQueryValueEx( hProfileKey, NS4_USERPATH_REG_KEY, NULL, &dwType,
  568. (LPBYTE)sProfilePath, &cProfilePathSize)
  569. != ERROR_SUCCESS)
  570. || dwType != REG_SZ)
  571. {
  572. goto doneWithEntryInPopulateExternalListForCookiesOrBookmarksWithNS4Entries;
  573. }
  574. cProfilePathSize /= sizeof(TCHAR);
  575. if( (MAX_PATH - cProfilePathSize) < cFilenameLength)
  576. {
  577. goto doneWithEntryInPopulateExternalListForCookiesOrBookmarksWithNS4Entries;
  578. }
  579. // append "\\sFilename\0" to the path.
  580. sProfilePath[ cProfilePathSize - 1] = TCHAR(FILENAME_SEPARATOR);
  581. memcpy( &sProfilePath[cProfilePathSize],
  582. sFilename, cFilenameLength * sizeof(TCHAR));
  583. cProfilePathSize += cFilenameLength;
  584. sProfilePath[cProfilePathSize++] = TCHAR('\0');
  585. // we can only import files if they exist!
  586. if( m_TransferType == IMPORT
  587. && GetFileAttributes(sProfilePath) == 0xFFFFFFFF)
  588. goto doneWithEntryInPopulateExternalListForCookiesOrBookmarksWithNS4Entries;
  589. //
  590. // construct the string for the combo box
  591. //
  592. TCHAR sRawProfileName[MAX_PATH];
  593. TCHAR sRealProfileName[MAX_PATH];
  594. UINT cRealProfileName;
  595. MLLoadString(IDS_NS4_FRIENDLY_PROFILE_NAME, sRawProfileName, MAX_PATH);
  596. cRealProfileName =
  597. wnsprintf(sRealProfileName, MAX_PATH,
  598. sRawProfileName, sProfileName);
  599. // Insert the profile into the list. If it inserts, thats
  600. //enough to consider the whole functions call a success.
  601. if( iterator.Insert(sRealProfileName, cRealProfileName + 1,
  602. sProfilePath, cProfilePathSize))
  603. retVal = TRUE;
  604. doneWithEntryInPopulateExternalListForCookiesOrBookmarksWithNS4Entries:
  605. if( hProfileKey != NULL)
  606. RegCloseKey(hProfileKey);
  607. }
  608. donePopulateExternalListForCookiesOrBookmarksWithNS4Entries:
  609. if( hUserRootKey != NULL)
  610. RegCloseKey( hUserRootKey);
  611. return retVal;
  612. }
  613. BOOL ImpExpUserProcess::populateExternalListFromFolders(LPTSTR pszPath)
  614. {
  615. BOOL retval = FALSE;
  616. TCHAR szFileName[MAX_PATH];
  617. TCHAR szPathWithWildcards[MAX_PATH];
  618. ListIterator iterator = (ListIterator)m_ExternalList;
  619. HANDLE hFind = NULL;
  620. WIN32_FIND_DATA wfd;
  621. //
  622. // what are we looking for?
  623. //
  624. if(m_ExternalType == BOOKMARKS)
  625. MLLoadString(IDS_NETSCAPE_BOOKMARK_FILE,szFileName,ARRAYSIZE(szFileName));
  626. else
  627. MLLoadString(IDS_NETSCAPE_COOKIE_FILE,szFileName,ARRAYSIZE(szFileName));
  628. //
  629. // prepare the path variable
  630. //
  631. StrCpyN(szPathWithWildcards,pszPath,MAX_PATH);
  632. StrCatBuff(szPathWithWildcards,ALL_FILES_WILDCARD,MAX_PATH);
  633. //
  634. // start the find file thing
  635. //
  636. hFind = FindFirstFile(szPathWithWildcards,&wfd);
  637. if (hFind == INVALID_HANDLE_VALUE)
  638. goto Cleanup;
  639. do
  640. {
  641. //
  642. // the actual bookmark or cookie file
  643. //
  644. TCHAR szFullPath[MAX_PATH];
  645. int cchFullPath;
  646. //
  647. // a "friendly" name for the corresponding profile
  648. //
  649. TCHAR szProfileFormat[MAX_PATH];
  650. TCHAR szProfileName[MAX_PATH];
  651. int cchProfileName;
  652. //
  653. // skip over "." and ".."
  654. //
  655. if(!StrCmp(wfd.cFileName, DOT_DIR) ||
  656. !StrCmp(wfd.cFileName, DOT_DOT_DIR))
  657. continue;
  658. //
  659. // skip over any non-directories
  660. //
  661. if (!(wfd.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY))
  662. continue;
  663. //
  664. // generate the path
  665. //
  666. #ifndef UNIX
  667. cchFullPath = wnsprintf(szFullPath,MAX_PATH,TEXT("%s\\%s\\%s"),pszPath,wfd.cFileName,szFileName);
  668. #else
  669. cchFullPath = wnsprintf(szFullPath,MAX_PATH,TEXT("%s/%s/%s"),pszPath,wfd.cFileName,szFileName);
  670. #endif
  671. //
  672. // see if the file actually exists
  673. //
  674. if (GetFileAttributes(szFullPath) == 0xFFFFFFFF)
  675. continue;
  676. //
  677. // generate the profile name
  678. //
  679. MLLoadString(IDS_FB_FRIENDLY_PROFILE_NAME, szProfileFormat, MAX_PATH);
  680. cchProfileName = wnsprintf(szProfileName, MAX_PATH, szProfileFormat, wfd.cFileName);
  681. //
  682. // add the entry to the list
  683. //
  684. iterator.Insert(
  685. szProfileName,cchProfileName+1,
  686. szFullPath,cchFullPath+1);
  687. retval = TRUE;
  688. } while(FindNextFile(hFind,&wfd));
  689. Cleanup:
  690. if (hFind)
  691. FindClose(hFind);
  692. return retval;
  693. }
  694. BOOL ImpExpUserProcess::populateExternalListWithNSEntriesFallBack()
  695. {
  696. BOOL retVal = FALSE;
  697. HKEY hRoot = NULL;
  698. HKEY hCurrentVersion = NULL;
  699. HKEY hCurrentVersionMain = NULL;
  700. TCHAR szUsersDir[64]; // will contain "..\\Users"
  701. DWORD dwType;
  702. TCHAR szVersion[64];
  703. TCHAR szPath[MAX_PATH];
  704. DWORD cbSize;
  705. LONG result;
  706. //
  707. // Open the root of netscape's HKLM registry hierarchy
  708. //
  709. result = RegOpenKeyEx(
  710. HKEY_LOCAL_MACHINE,
  711. NS_FALLBACK_ROOT_REG_KEY,
  712. 0,
  713. KEY_READ,
  714. &hRoot);
  715. if (result != ERROR_SUCCESS)
  716. goto Cleanup;
  717. //
  718. // Retrieve the "CurrentVersion" value
  719. //
  720. cbSize = sizeof(szVersion);
  721. result = RegQueryValueEx(
  722. hRoot,
  723. NS_FALLBACK_VERSION_REG_VAL,
  724. NULL,
  725. &dwType,
  726. (LPBYTE)szVersion,
  727. &cbSize);
  728. if (result != ERROR_SUCCESS || dwType != REG_SZ)
  729. goto Cleanup;
  730. //
  731. // Open the sub-hierarchy corresponding to the current version
  732. //
  733. result = RegOpenKeyEx(
  734. hRoot,
  735. szVersion,
  736. 0,
  737. KEY_READ,
  738. &hCurrentVersion);
  739. if (result != ERROR_SUCCESS)
  740. goto Cleanup;
  741. //
  742. // Open the "main" sub-hierarchy
  743. //
  744. result = RegOpenKeyEx(
  745. hCurrentVersion,
  746. NS_FALLBACK_MAIN_REG_VAL,
  747. 0,
  748. KEY_READ,
  749. &hCurrentVersionMain);
  750. if (result != ERROR_SUCCESS)
  751. goto Cleanup;
  752. //
  753. // Retrieve the "Install Directory" value
  754. //
  755. cbSize = sizeof(szPath);
  756. result = RegQueryValueEx(
  757. hCurrentVersionMain,
  758. NS_FALLBACK_INST_REG_VAL,
  759. NULL,
  760. &dwType,
  761. (LPBYTE)szPath,
  762. &cbSize);
  763. if (result != ERROR_SUCCESS || dwType != REG_SZ)
  764. goto Cleanup;
  765. //
  766. // Take a wild guess at where the "Users" dir might be
  767. //
  768. MLLoadString(IDS_NETSCAPE_USERS_DIR,szUsersDir,ARRAYSIZE(szUsersDir));
  769. StrCatBuff(szPath,szUsersDir,ARRAYSIZE(szPath));
  770. //
  771. // Fill in the list
  772. //
  773. if (populateExternalListFromFolders(szPath))
  774. retVal = TRUE;
  775. Cleanup:
  776. if (hRoot)
  777. RegCloseKey(hRoot);
  778. if (hCurrentVersion)
  779. RegCloseKey(hCurrentVersion);
  780. if (hCurrentVersionMain)
  781. RegCloseKey(hCurrentVersionMain);
  782. return retVal;
  783. }
  784. //*************************************************************
  785. //
  786. // PopulateTreeViewForInternalSelection
  787. //
  788. // Load a nested list of the favorites folders into memory
  789. //and then into a Tree View.
  790. // returns FALSE if TreeView is left empty.
  791. BOOL ImpExpUserProcess::PopulateTreeViewForInternalSelection( HWND hTreeView)
  792. {
  793. ASSERT( m_TransferType != INVALID_TRANSFER);
  794. TreeView_DeleteAllItems( hTreeView);
  795. if( !populateInternalList())
  796. return FALSE;
  797. return populateTreeViewWithInternalList
  798. ( hTreeView, (ListIterator)m_InternalList, TVI_ROOT);
  799. }
  800. //*************************************************************
  801. //
  802. // populateTreeViewWithInternalList
  803. //
  804. // Loads list entries at 'iterator' below tree view item 'hParent'
  805. // into 'hTreeView'. Associates value of each list entry with
  806. // the Param of the Tree View node.
  807. //
  808. BOOL ImpExpUserProcess::populateTreeViewWithInternalList
  809. (
  810. HWND hTreeView,
  811. ListIterator iterator,
  812. HTREEITEM hParent
  813. )
  814. {
  815. BOOL retVal = FALSE;
  816. if( iterator.AtEndOfList())
  817. goto donePopulateTreeViewWithInternalList;
  818. TVINSERTSTRUCT newTV;
  819. HTREEITEM hNew;
  820. // declare parent and intent to put at end of list.
  821. newTV.hParent = hParent;
  822. newTV.hInsertAfter = TVI_LAST;
  823. // build info struct
  824. newTV.itemex.mask = TVIF_TEXT
  825. | TVIF_PARAM
  826. | TVIF_CHILDREN
  827. | TVIF_IMAGE
  828. | TVIF_SELECTEDIMAGE;
  829. // give name
  830. newTV.itemex.cchTextMax = lstrlen( iterator.GetName()) + 1;
  831. newTV.itemex.pszText = const_cast<LPTSTR>(iterator.GetName());
  832. // associate the necessary data
  833. newTV.itemex.lParam = (LPARAM)iterator.GetValue();
  834. // tell tree view if there are any children.
  835. newTV.itemex.cChildren =
  836. iterator.GetSublist().AtEndOfList() == TRUE ? FALSE : TRUE;
  837. // use correct icons
  838. newTV.itemex.iSelectedImage = FOLDER_OPEN ;
  839. newTV.itemex.iImage = FOLDER_CLOSED ;
  840. hNew = TreeView_InsertItem( hTreeView, &newTV );
  841. if( hNew == NULL)
  842. goto donePopulateTreeViewWithInternalList;
  843. // an element has been added, so we should return TRUE.
  844. retVal = TRUE;
  845. // add children
  846. populateTreeViewWithInternalList( hTreeView, iterator.GetSublist(), hNew );
  847. // add siblings
  848. if( iterator.Next())
  849. populateTreeViewWithInternalList( hTreeView, iterator, hParent );
  850. donePopulateTreeViewWithInternalList:
  851. return retVal;
  852. }
  853. BOOL ImpExpUserProcess::ExpandTreeViewRoot ( HWND hTreeView )
  854. {
  855. HTREEITEM hRoot ;
  856. hRoot = TreeView_GetRoot ( hTreeView ) ;
  857. if ( hRoot != NULL )
  858. TreeView_Expand ( hTreeView, hRoot, TVE_EXPAND ) ;
  859. else
  860. return FALSE ;
  861. return TRUE ;
  862. }
  863. //*************************************************************
  864. //
  865. // SelectInternalSelection
  866. //
  867. // Gets the data associated with the current selection of
  868. //'hTreeView'.
  869. BOOL ImpExpUserProcess::SelectInternalSelection( HWND hTreeView)
  870. {
  871. HTREEITEM hSelection = TreeView_GetSelection( hTreeView);
  872. if( hSelection == NULL)
  873. return FALSE;
  874. //TVITEM is built up to query the lParam
  875. //(the lParam has been associated with a pointer to the path value)
  876. TVITEM TV;
  877. TV.mask = TVIF_PARAM;
  878. TV.hItem = hSelection;
  879. if( !TreeView_GetItem( hTreeView, &TV))
  880. return FALSE;
  881. m_pSelectedInternal = (LPTSTR)TV.lParam;
  882. ASSERT( m_pSelectedInternal != NULL);
  883. return TRUE;
  884. }
  885. //*************************************************************
  886. //
  887. // purgeInternalList
  888. //
  889. // Wipes out whatever has been loaded in the internal
  890. //target/source list.
  891. void ImpExpUserProcess::purgeInternalList()
  892. {
  893. // clear the list.
  894. ListIterator iterator = (ListIterator)m_InternalList;
  895. while( iterator.Remove())
  896. {
  897. }
  898. m_pSelectedInternal = NULL;
  899. m_InternalListExternalType = INVALID_EXTERNAL;
  900. m_InternalListTransferType = INVALID_TRANSFER;
  901. }
  902. //*************************************************************
  903. //
  904. // populateInternalList
  905. //
  906. // Builds the internal list for potential internal target/sources.
  907. // This currently only makes sense for bookmarks, where a favorites
  908. //directory has to be picked.
  909. // returns TRUE if any elements have been added to the internal list
  910. BOOL ImpExpUserProcess::populateInternalList()
  911. {
  912. ASSERT( m_ExternalType != INVALID_EXTERNAL);
  913. if( m_InternalListExternalType == m_ExternalType
  914. && m_InternalListTransferType == m_TransferType)
  915. return TRUE;
  916. purgeInternalList();
  917. // (could switch on different m_ExternalTypes here)
  918. if( !populateInternalListForBookmarks())
  919. {
  920. purgeInternalList();
  921. return FALSE;
  922. }
  923. m_InternalListExternalType = m_ExternalType;
  924. m_InternalListTransferType = m_TransferType;
  925. return TRUE;
  926. }
  927. //*************************************************************
  928. //
  929. // populateInternalListForBookmarks
  930. // returns TRUE if any elements have been added to the internal list
  931. BOOL ImpExpUserProcess::populateInternalListForBookmarks()
  932. {
  933. TCHAR szFavoritesPath[MAX_PATH];
  934. if( SHGetSpecialFolderPath( NULL, szFavoritesPath, CSIDL_FAVORITES, FALSE)
  935. && appendSubdirsToInternalList( szFavoritesPath, m_InternalList))
  936. {
  937. return TRUE;
  938. }
  939. else return FALSE;
  940. }
  941. //*************************************************************
  942. //
  943. // appendSubdirsToInternalList
  944. //
  945. // Takes 'sPath' as a specification for a file search. All
  946. //directories that match that are added to the internal list
  947. //at 'iterator'.
  948. // Recursively adds subdirectories found.
  949. //
  950. //typical usage:
  951. // szPath is "c:\Root\Favorites",
  952. // finds "c:\Root\Favorites",
  953. // recursively calls itself with
  954. // szPath = "c:\Root\Favorites\*.*"
  955. // finding and recursing into all subdirs
  956. // returns TRUE if any directories have been added to the internal list
  957. // Edits the contents of the buffer past the last '\\'.
  958. BOOL ImpExpUserProcess::appendSubdirsToInternalList
  959. (
  960. LPTSTR sPath,
  961. ListIterator iterator
  962. )
  963. {
  964. BOOL fHaveAddedDirectories = FALSE;
  965. DWORD cPathLength = lstrlen(sPath);
  966. HANDLE hEnum;
  967. WIN32_FIND_DATA currentFile;
  968. hEnum = FindFirstFile( sPath, &currentFile);
  969. //example:
  970. //given: "c:\root\*.*" (will find all dirs in root)
  971. //want: "c:\root\"
  972. //given: "c:\favorites" (will find favorites in root)
  973. //want: "c:\"
  974. // left search to '\\' to find the path of the files to be found.
  975. while( cPathLength > 0
  976. && sPath[ --cPathLength] != TCHAR(FILENAME_SEPARATOR))
  977. {
  978. }
  979. cPathLength++;
  980. if( hEnum == INVALID_HANDLE_VALUE)
  981. return FALSE;
  982. do
  983. {
  984. DWORD cFileNameLength;
  985. // we only handle directories
  986. if( !(currentFile.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY))
  987. continue;
  988. // we don't want '.' and '..' to show up.
  989. if( !StrCmp( currentFile.cFileName, DOT_DIR)
  990. || !StrCmp( currentFile.cFileName, DOT_DOT_DIR))
  991. continue;
  992. cFileNameLength = lstrlen( currentFile.cFileName);
  993. memcpy( sPath + cPathLength, currentFile.cFileName, cFileNameLength * sizeof(TCHAR));
  994. sPath[ cPathLength + cFileNameLength] = TCHAR('\0');
  995. if( iterator.Insert( currentFile.cFileName, cFileNameLength + 1,
  996. sPath, cPathLength + cFileNameLength + 1))
  997. {
  998. memcpy( sPath + cPathLength + cFileNameLength,
  999. ALL_FILES_WILDCARD, sizeof(ALL_FILES_WILDCARD));
  1000. appendSubdirsToInternalList( sPath, iterator.GetSublist());
  1001. // we know now that a directory has been added
  1002. fHaveAddedDirectories = TRUE;
  1003. }
  1004. } while( FindNextFile( hEnum, &currentFile));
  1005. ASSERT(ERROR_NO_MORE_FILES == GetLastError());
  1006. FindClose(hEnum);
  1007. return fHaveAddedDirectories;
  1008. }
  1009. //*************************************************************
  1010. //
  1011. // PerformImpExpProcess
  1012. //
  1013. // Once everything is set up right, this should do the trick.
  1014. void ImpExpUserProcess::PerformImpExpProcess(HWND hwnd)
  1015. {
  1016. ASSERT( GetExternalType() != INVALID_EXTERNAL);
  1017. ASSERT( GetTransferType() != INVALID_TRANSFER);
  1018. ASSERT( (GetExternalType() == BOOKMARKS) ? (GetInternalSelection() != NULL) : TRUE);
  1019. HCURSOR hOldCursor;
  1020. //
  1021. // This could take a while, so show an hourglass cursor
  1022. //
  1023. hOldCursor = SetCursor(LoadCursor(NULL, IDC_WAIT));
  1024. switch( GetExternalType())
  1025. {
  1026. case COOKIES:
  1027. switch( GetTransferType())
  1028. {
  1029. case IMPORT:
  1030. if (ImportCookieFile(m_szFileName))
  1031. {
  1032. MLShellMessageBox(
  1033. hwnd,
  1034. MAKEINTRESOURCE(IDS_IMPORTSUCCESS_COOK),
  1035. MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_COOK),
  1036. MB_OK);
  1037. }
  1038. else
  1039. {
  1040. MLShellMessageBox(
  1041. hwnd,
  1042. MAKEINTRESOURCE(IDS_IMPORTFAILURE_COOK),
  1043. MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_COOK),
  1044. MB_OK);
  1045. }
  1046. break;
  1047. case EXPORT:
  1048. if (SUCCEEDED(SHPathPrepareForWriteWrap(hwnd, NULL, m_szFileName, FO_COPY, (SHPPFW_DEFAULT | SHPPFW_IGNOREFILENAME))))
  1049. {
  1050. // FALSE specifies that we will overwrite cookies
  1051. if (ExportCookieFile(m_szFileName, FALSE ))
  1052. {
  1053. MLShellMessageBox(
  1054. hwnd,
  1055. MAKEINTRESOURCE(IDS_EXPORTSUCCESS_COOK),
  1056. MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_COOK),
  1057. MB_OK);
  1058. }
  1059. else
  1060. {
  1061. MLShellMessageBox(
  1062. hwnd,
  1063. MAKEINTRESOURCE(IDS_EXPORTFAILURE_COOK),
  1064. MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_COOK),
  1065. MB_OK);
  1066. }
  1067. }
  1068. break;
  1069. default:
  1070. ASSERT(0);
  1071. }
  1072. break;
  1073. case BOOKMARKS:
  1074. DoImportOrExport(
  1075. GetTransferType()==IMPORT,
  1076. m_pSelectedInternal,
  1077. m_szFileName,
  1078. FALSE);
  1079. break;
  1080. default:
  1081. ASSERT(0);
  1082. }
  1083. //
  1084. // Put the old cursor back when finished
  1085. //
  1086. SetCursor(hOldCursor);
  1087. }
  1088. //*************************************************************
  1089. //*************************************************************
  1090. //
  1091. // ImpExpUserDlg
  1092. //
  1093. // Handles the user interface side of things, building
  1094. // up an ImpExpUserProcess then executing it.
  1095. // The dialog procedures below will all have a return value
  1096. // which can be set to something besides FALSE if used, or left
  1097. // as FALSE if not used. Since only one section of code should
  1098. // attempt to give the return value a value before returning,
  1099. // class RetVal is set up to throw an assertion if two pieces
  1100. // of code intended to pass back a return value at the same
  1101. // time.
  1102. class ReturnValue
  1103. {
  1104. private:
  1105. BOOL_PTR m_value;
  1106. public:
  1107. ReturnValue()
  1108. {
  1109. m_value = FALSE;
  1110. }
  1111. BOOL_PTR operator =(BOOL_PTR newVal)
  1112. {
  1113. ASSERT( m_value == FALSE);
  1114. m_value = newVal;
  1115. return m_value;
  1116. }
  1117. operator BOOL_PTR ()
  1118. {
  1119. return m_value;
  1120. }
  1121. };
  1122. class ImpExpUserDlg
  1123. {
  1124. private:
  1125. static HIMAGELIST m_himl ;
  1126. static BOOL InitImageList ( HWND hwndTree ) ;
  1127. static BOOL DestroyImageList ( HWND hwndTree ) ;
  1128. static HFONT m_hfont ;
  1129. static BOOL InitFont ( HWND hwndStatic ) ;
  1130. static BOOL DestroyFont ( HWND hwndStatic ) ;
  1131. // A sheet knows its resource ID and what process
  1132. //it contributes to.
  1133. struct SheetData
  1134. {
  1135. int _idPage;
  1136. ImpExpUserProcess* _pImpExp;
  1137. SheetData( int idPage, ImpExpUserProcess* pImpExp )
  1138. : _idPage( idPage ), _pImpExp( pImpExp )
  1139. {
  1140. }
  1141. };
  1142. //
  1143. // InitializePropertySheetPage() will associate a dialog
  1144. // with an allocated copy of SheetData, which will be
  1145. // found at PSN_SETACTIVE with and stored with SetWindowLong.
  1146. // The allocated SheetData will be cleaned up by callback
  1147. // procedure PropertySheetPageProc().
  1148. //
  1149. // Callback functions sure are a drag for maintaining identity.
  1150. // GetWindowLong and SetWindowLong will be used to keep tabs
  1151. // on who is who, setting 'ghost' member variables.
  1152. //
  1153. // 'ghost' SheetData* This;
  1154. // 'ghost' ImpExpUserProcess* m_pImpExp;
  1155. // 'ghost' DWORD m_idPage;
  1156. //
  1157. // CommonDialogProc retrieves the 'ghost' values and does other
  1158. // shared behavior.
  1159. //
  1160. static DWORD CommonDialogProc
  1161. (
  1162. IN HWND hwndDlg, IN UINT msg, IN WPARAM wParam, IN LPARAM lParam,
  1163. OUT ImpExpUserProcess** ppImpExp, OUT DWORD* pPageId,
  1164. IN OUT ReturnValue& retVal
  1165. );
  1166. static void InitializePropertySheetPage( PROPSHEETPAGE* psp, DWORD idDialogTemplate, DWORD idTitle, DWORD idSubTitle,DLGPROC dlgProc, ImpExpUserProcess* lParam);
  1167. static UINT CALLBACK PropertySheetPageProc( HWND hwnd, UINT uMsg, LPPROPSHEETPAGE ppsp);
  1168. // some dialog procedures
  1169. static BOOL_PTR CALLBACK Wizard97DlgProc( HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  1170. static BOOL_PTR CALLBACK TransferTypeDlg(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  1171. static BOOL_PTR CALLBACK InternalDlg(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  1172. static BOOL_PTR CALLBACK ExternalDlg(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam);
  1173. static void HandleTransferTypeChange ( HWND hwndDlg, ImpExpUserProcess* m_pImpExp, UINT iSelect ) ;
  1174. public:
  1175. static BOOL RunNewDialogProcess( HWND hParent ) ;
  1176. };
  1177. HIMAGELIST ImpExpUserDlg::m_himl = NULL ;
  1178. BOOL ImpExpUserDlg::InitImageList ( HWND hwndTree )
  1179. {
  1180. //
  1181. // Code to retrieve icons for open and closed folders
  1182. // was based on code in private/samples/sampview/utility.cpp.
  1183. //
  1184. TCHAR szFolder[MAX_PATH];
  1185. SHFILEINFO sfi;
  1186. HIMAGELIST himlOld ;
  1187. DWORD dwRet ;
  1188. // create the image list
  1189. m_himl = ImageList_Create ( GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), ILC_COLORDDB, 2, 2 ) ;
  1190. if ( m_himl == NULL )
  1191. return FALSE ;
  1192. ImageList_SetBkColor( m_himl, GetSysColor(COLOR_WINDOW) ) ;
  1193. // add the closed folder icon
  1194. GetWindowsDirectory(szFolder, MAX_PATH);
  1195. SHGetFileInfo( szFolder,
  1196. 0,
  1197. &sfi,
  1198. sizeof(sfi),
  1199. SHGFI_ICON | SHGFI_SMALLICON);
  1200. dwRet = ImageList_AddIcon(m_himl, sfi.hIcon);
  1201. ASSERT ( dwRet == FOLDER_CLOSED ) ;
  1202. // add the open folder icon
  1203. SHGetFileInfo( szFolder,
  1204. 0,
  1205. &sfi,
  1206. sizeof(sfi),
  1207. SHGFI_ICON | SHGFI_SMALLICON | SHGFI_OPENICON);
  1208. dwRet = ImageList_AddIcon(m_himl, sfi.hIcon);
  1209. ASSERT ( dwRet == FOLDER_OPEN ) ;
  1210. himlOld = TreeView_SetImageList( hwndTree, m_himl, TVSIL_NORMAL );
  1211. if ( himlOld != NULL )
  1212. {
  1213. BOOL fOk ;
  1214. fOk = ImageList_Destroy ( himlOld ) ;
  1215. ASSERT ( fOk ) ;
  1216. }
  1217. return TRUE ;
  1218. }
  1219. BOOL ImpExpUserDlg::DestroyImageList ( HWND hwndTree )
  1220. {
  1221. HIMAGELIST himlOld ;
  1222. himlOld = TreeView_SetImageList( hwndTree, NULL, TVSIL_NORMAL );
  1223. if ( himlOld != NULL )
  1224. {
  1225. BOOL fOk ;
  1226. fOk = ImageList_Destroy ( himlOld ) ;
  1227. ASSERT ( fOk ) ;
  1228. }
  1229. return TRUE ;
  1230. }
  1231. HFONT ImpExpUserDlg::m_hfont = NULL ;
  1232. BOOL ImpExpUserDlg::InitFont ( HWND hwndStatic )
  1233. {
  1234. HDC hdc = GetDC ( hwndStatic ) ;
  1235. if ( hdc == NULL )
  1236. return FALSE ;
  1237. LOGFONT lf;
  1238. lf.lfEscapement = 0;
  1239. lf.lfOrientation = 0;
  1240. lf.lfOutPrecision = OUT_DEFAULT_PRECIS;
  1241. lf.lfClipPrecision = CLIP_DEFAULT_PRECIS;
  1242. lf.lfQuality = DEFAULT_QUALITY;
  1243. lf.lfPitchAndFamily = DEFAULT_PITCH;
  1244. lf.lfItalic = 0;
  1245. lf.lfWeight = FW_BOLD;
  1246. lf.lfStrikeOut = 0;
  1247. lf.lfUnderline = 0;
  1248. lf.lfWidth = 0;
  1249. lf.lfHeight = -MulDiv(13, GetDeviceCaps(hdc, LOGPIXELSY), 72);
  1250. LOGFONT lfTmp;
  1251. HFONT hFontOrig = (HFONT)SendMessage(hwndStatic, WM_GETFONT, (WPARAM)0, (LPARAM)0);
  1252. if (hFontOrig && GetObject(hFontOrig, sizeof(lfTmp), &lfTmp))
  1253. {
  1254. lf.lfCharSet = lfTmp.lfCharSet;
  1255. StrCpyN(lf.lfFaceName, lfTmp.lfFaceName, LF_FACESIZE);
  1256. }
  1257. else
  1258. {
  1259. lf.lfCharSet = GetTextCharset(hdc);
  1260. StrCpyN(lf.lfFaceName, TEXT("MS Shell Dlg"), LF_FACESIZE);
  1261. }
  1262. m_hfont = CreateFontIndirect(&lf);
  1263. if ( m_hfont == NULL )
  1264. {
  1265. ReleaseDC(hwndStatic, hdc);
  1266. return FALSE ;
  1267. }
  1268. SendMessage ( hwndStatic, WM_SETFONT, (WPARAM)m_hfont, MAKELPARAM(FALSE, 0) ) ;
  1269. ReleaseDC ( hwndStatic,hdc ) ;
  1270. return TRUE ;
  1271. }
  1272. BOOL ImpExpUserDlg::DestroyFont ( HWND hwndDlg )
  1273. {
  1274. if ( m_hfont )
  1275. DeleteObject ( m_hfont ) ;
  1276. return TRUE ;
  1277. }
  1278. void ImpExpUserDlg::InitializePropertySheetPage
  1279. (
  1280. PROPSHEETPAGE* psp,
  1281. DWORD idDialogTemplate,
  1282. DWORD idTitle,
  1283. DWORD idSubTitle,
  1284. DLGPROC dlgProc,
  1285. ImpExpUserProcess* lParam
  1286. )
  1287. {
  1288. psp->dwFlags |= PSP_USECALLBACK | PSP_USETITLE;
  1289. psp->hInstance = MLGetHinst();
  1290. psp->pszTemplate = MAKEINTRESOURCE(idDialogTemplate);
  1291. psp->pfnDlgProc = dlgProc;
  1292. psp->lParam = (LPARAM)(new SheetData(idDialogTemplate,lParam));
  1293. psp->pfnCallback = PropertySheetPageProc;
  1294. psp->pszHeaderTitle = MAKEINTRESOURCE(idTitle);
  1295. psp->pszHeaderSubTitle = MAKEINTRESOURCE(idSubTitle);
  1296. psp->pszTitle = MAKEINTRESOURCE(IDS_IMPEXP_CAPTION);
  1297. if ( idDialogTemplate == IDD_IMPEXPWELCOME ||
  1298. idDialogTemplate == IDD_IMPEXPCOMPLETE )
  1299. {
  1300. psp->dwFlags |= PSP_HIDEHEADER;
  1301. }
  1302. else
  1303. {
  1304. psp->dwFlags |= (PSP_USEHEADERTITLE | PSP_USEHEADERSUBTITLE);
  1305. }
  1306. }
  1307. UINT CALLBACK ImpExpUserDlg::PropertySheetPageProc
  1308. (
  1309. HWND hwnd,
  1310. UINT uMsg,
  1311. LPPROPSHEETPAGE ppsp
  1312. )
  1313. {
  1314. switch(uMsg)
  1315. {
  1316. case PSPCB_CREATE:
  1317. break;
  1318. case PSPCB_RELEASE:
  1319. delete (SheetData*)ppsp->lParam;
  1320. ppsp->lParam = NULL;
  1321. break;
  1322. default:
  1323. break;
  1324. }
  1325. return TRUE ;
  1326. }
  1327. //*************************************************************
  1328. //
  1329. // RunNewDialogProcess
  1330. //
  1331. // Runs the Import Export Wizard.
  1332. BOOL_PTR CALLBACK TEMP(
  1333. HWND hwndDlg, // handle to dialog box
  1334. UINT uMsg, // message
  1335. WPARAM wParam, // first message parameter
  1336. LPARAM lParam // second message parameter
  1337. )
  1338. {
  1339. return (uMsg==WM_INITDIALOG);
  1340. }
  1341. BOOL ImpExpUserDlg::RunNewDialogProcess(HWND hParent)
  1342. {
  1343. const int numPages = 9;
  1344. ImpExpUserProcess* pImpExp = new ImpExpUserProcess();
  1345. if( pImpExp == NULL)
  1346. return FALSE;
  1347. PROPSHEETPAGE pspOld[numPages];
  1348. PROPSHEETPAGE* psp = pspOld;
  1349. // dwSkip is set in Whistler_AllocatePropertySheetPage to whatever the size of Whistler's PROPSHEETPAGE
  1350. // is. 0x34 last I checked. (IE5 PROPSHEETPAGE is 0x30)
  1351. DWORD dwSkip = sizeof(PROPSHEETPAGE);
  1352. if (IsOS(OS_WHISTLERORGREATER))
  1353. {
  1354. PROPSHEETPAGE* psp2 = Whistler_AllocatePropertySheetPage(numPages, &dwSkip);
  1355. if (psp2)
  1356. {
  1357. psp = psp2;
  1358. }
  1359. }
  1360. if (psp==pspOld)
  1361. {
  1362. for (int i=0; i<numPages; i++)
  1363. {
  1364. memset(&psp[i], 0, sizeof(PROPSHEETPAGE));
  1365. psp[i].dwSize = sizeof(PROPSHEETPAGE);
  1366. }
  1367. }
  1368. PROPSHEETHEADER psh;
  1369. PBYTE pspNext = (PBYTE)psp;
  1370. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPWELCOME, 0, 0, Wizard97DlgProc, pImpExp );
  1371. pspNext += dwSkip;
  1372. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPTRANSFERTYPE, IDS_IMPEXPTRANSFERTYPE_TITLE, IDS_IMPEXPTRANSFERTYPE_SUBTITLE, TransferTypeDlg, pImpExp );
  1373. pspNext += dwSkip;
  1374. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPIMPFAVSRC, IDS_IMPEXPIMPFAVSRC_TITLE, IDS_IMPEXPIMPFAVSRC_SUBTITLE, ExternalDlg, pImpExp );
  1375. pspNext += dwSkip;
  1376. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPIMPFAVDES, IDS_IMPEXPIMPFAVDES_TITLE, IDS_IMPEXPIMPFAVDES_SUBTITLE, InternalDlg, pImpExp );
  1377. pspNext += dwSkip;
  1378. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPEXPFAVSRC, IDS_IMPEXPEXPFAVSRC_TITLE, IDS_IMPEXPEXPFAVSRC_SUBTITLE, InternalDlg, pImpExp );
  1379. pspNext += dwSkip;
  1380. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPEXPFAVDES, IDS_IMPEXPEXPFAVDES_TITLE, IDS_IMPEXPEXPFAVDES_SUBTITLE, ExternalDlg, pImpExp );
  1381. pspNext += dwSkip;
  1382. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPIMPCKSRC, IDS_IMPEXPIMPCKSRC_TITLE, IDS_IMPEXPIMPCKSRC_SUBTITLE, ExternalDlg, pImpExp );
  1383. pspNext += dwSkip;
  1384. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPEXPCKDES, IDS_IMPEXPEXPCKDES_TITLE, IDS_IMPEXPEXPCKDES_SUBTITLE, ExternalDlg, pImpExp );
  1385. pspNext += dwSkip;
  1386. InitializePropertySheetPage( (PROPSHEETPAGE*)pspNext, IDD_IMPEXPCOMPLETE, 0, 0, Wizard97DlgProc, pImpExp );
  1387. psh.dwSize = sizeof(PROPSHEETHEADER);
  1388. psh.dwFlags = PSH_WIZARD97 | PSH_PROPSHEETPAGE | PSH_HEADER | PSH_WATERMARK ;
  1389. psh.hwndParent = hParent;
  1390. psh.hInstance = MLGetHinst();
  1391. psh.pszCaption = MAKEINTRESOURCE(IDS_IMPEXP_CAPTION);
  1392. psh.nPages = numPages;
  1393. psh.nStartPage = 0;
  1394. psh.ppsp = psp;
  1395. psh.pszbmWatermark = MAKEINTRESOURCE(IDB_IMPEXPWATERMARK);
  1396. psh.pszbmHeader = MAKEINTRESOURCE(IDB_IMPEXPHEADER);
  1397. ULONG_PTR uCookie = 0;
  1398. SHActivateContext(&uCookie);
  1399. int iResult = (int)PropertySheet(&psh) ;
  1400. if (uCookie)
  1401. {
  1402. SHDeactivateContext(uCookie);
  1403. }
  1404. delete pImpExp;
  1405. if (psp!=pspOld)
  1406. {
  1407. HeapFree(GetProcessHeap(), NULL, psp);
  1408. }
  1409. return iResult;
  1410. }
  1411. //*************************************************************
  1412. //
  1413. // CommonDialogProc
  1414. //
  1415. // Prepares 'ghost' member variables of the user dialog process,
  1416. // handles ordering details of wizard pages and initializes common
  1417. // dialog elements.
  1418. //
  1419. // retVal passes through CommonDialogProc so that it can be set
  1420. // if necessary. Clients of CommonDialogProc should not need
  1421. // to specify a new return value if CommonDialogProc has specified
  1422. // a non-FALSE return value.
  1423. //
  1424. // If CommonDialogProc returns FALSE dialog procedure should
  1425. // considered 'msg' handled and return retVal immediately.
  1426. //
  1427. // If this dialog has yet to receive WM_INITDIALOG, the 'ghost'
  1428. // values will be zero (and invalid).
  1429. //
  1430. DWORD ImpExpUserDlg::CommonDialogProc
  1431. (
  1432. IN HWND hwndDlg,
  1433. IN UINT msg,
  1434. IN WPARAM wParam,
  1435. IN LPARAM lParam,
  1436. OUT ImpExpUserProcess** ppImpExp,
  1437. OUT DWORD* pPageId,
  1438. ReturnValue& retVal
  1439. )
  1440. {
  1441. SheetData* sheetData;
  1442. ImpExpUserProcess* m_pImpExp = NULL;
  1443. DWORD m_idPage = 0;
  1444. //
  1445. // Do init-dialog stuff
  1446. //
  1447. if ( WM_INITDIALOG == msg )
  1448. {
  1449. sheetData = (SheetData*)(((PROPSHEETPAGE*)lParam)->lParam);
  1450. SetWindowLongPtr( hwndDlg, DWLP_USER, (LONG_PTR)sheetData);
  1451. }
  1452. //
  1453. // Initialize the sheetData field
  1454. //
  1455. sheetData = (SheetData*)GetWindowLongPtr( hwndDlg, DWLP_USER ) ;
  1456. if ( sheetData != NULL )
  1457. {
  1458. m_pImpExp = *ppImpExp = sheetData->_pImpExp;
  1459. m_idPage = *pPageId = sheetData->_idPage;
  1460. }
  1461. //
  1462. // Next, we check to make sure we're on the correct page. If not, simply
  1463. // return -1 and the wizard will automatically advance to the next page.
  1464. //
  1465. if( WM_NOTIFY == msg && PSN_SETACTIVE == ((LPNMHDR)lParam)->code )
  1466. {
  1467. BOOL fPageValidation = TRUE ;
  1468. switch( m_idPage )
  1469. {
  1470. case IDD_IMPEXPWELCOME:
  1471. case IDD_IMPEXPTRANSFERTYPE:
  1472. case IDD_IMPEXPCOMPLETE:
  1473. break;
  1474. case IDD_IMPEXPIMPFAVSRC:
  1475. case IDD_IMPEXPIMPFAVDES:
  1476. if(m_pImpExp->GetTransferType() != IMPORT || m_pImpExp->GetExternalType() != BOOKMARKS)
  1477. fPageValidation = FALSE;
  1478. break;
  1479. case IDD_IMPEXPEXPFAVSRC:
  1480. case IDD_IMPEXPEXPFAVDES:
  1481. if(m_pImpExp->GetTransferType() != EXPORT || m_pImpExp->GetExternalType() != BOOKMARKS)
  1482. fPageValidation = FALSE;
  1483. break;
  1484. case IDD_IMPEXPIMPCKSRC:
  1485. if(m_pImpExp->GetTransferType() != IMPORT || m_pImpExp->GetExternalType() != COOKIES)
  1486. fPageValidation = FALSE;
  1487. break;
  1488. case IDD_IMPEXPEXPCKDES:
  1489. if(m_pImpExp->GetTransferType() != EXPORT || m_pImpExp->GetExternalType() != COOKIES)
  1490. fPageValidation = FALSE;
  1491. break;
  1492. }
  1493. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, fPageValidation ? 0 : -1 ) ;
  1494. retVal = TRUE ;
  1495. if ( ! fPageValidation )
  1496. return FALSE ;
  1497. }
  1498. //
  1499. // Initialize fonts and image lists (if needed)
  1500. //
  1501. if ( WM_NOTIFY == msg )
  1502. {
  1503. HWND hwndTitle = GetDlgItem ( hwndDlg, IDC_IMPEXPTITLETEXT ) ;
  1504. HWND hwndTree = GetDlgItem ( hwndDlg, IDC_IMPEXPFAVTREE ) ;
  1505. switch ( ((LPNMHDR)lParam)->code )
  1506. {
  1507. case PSN_SETACTIVE:
  1508. if ( hwndTitle )
  1509. InitFont ( hwndTitle ) ;
  1510. if ( hwndTree )
  1511. InitImageList( hwndTree ) ;
  1512. break ;
  1513. case PSN_KILLACTIVE:
  1514. case PSN_QUERYCANCEL:
  1515. if ( hwndTitle )
  1516. DestroyFont ( hwndTitle ) ;
  1517. if ( hwndTree )
  1518. DestroyImageList( hwndTree ) ;
  1519. break;
  1520. }
  1521. }
  1522. if( WM_NOTIFY == msg && PSN_SETACTIVE == ((LPNMHDR)lParam)->code )
  1523. {
  1524. HWND hwndParent = GetParent( hwndDlg);
  1525. switch( m_idPage )
  1526. {
  1527. case IDD_IMPEXPWELCOME:
  1528. PropSheet_SetWizButtons( hwndParent, PSWIZB_NEXT );
  1529. break;
  1530. case IDD_IMPEXPCOMPLETE:
  1531. {
  1532. UINT idText ;
  1533. const TCHAR *szInsert = m_pImpExp->m_szFileName ;
  1534. TCHAR szRawString[1024] ;
  1535. TCHAR szRealString[1024] ;
  1536. //
  1537. // First, we need to figure out which string should
  1538. // be used to describe what the wizard is going to
  1539. // do (for example "Import the cookies from...")
  1540. //
  1541. if ( m_pImpExp->GetTransferType() == IMPORT )
  1542. {
  1543. if ( m_pImpExp->GetExternalType() == COOKIES )
  1544. idText = IDS_IMPEXP_COMPLETE_IMPCK ;
  1545. else
  1546. idText = IDS_IMPEXP_COMPLETE_IMPFV ;
  1547. }
  1548. else
  1549. {
  1550. if ( m_pImpExp->GetExternalType() == COOKIES )
  1551. idText = IDS_IMPEXP_COMPLETE_EXPCK ;
  1552. else
  1553. idText = IDS_IMPEXP_COMPLETE_EXPFV ;
  1554. }
  1555. LoadString(MLGetHinst(), idText, szRawString, 1024);
  1556. wnsprintf(szRealString, 1024, szRawString, szInsert);
  1557. //
  1558. // Set the text in the listview, and do all the other magic to make
  1559. // the tooltips work, etc.
  1560. //
  1561. SetListViewToString(GetDlgItem(hwndDlg,IDC_IMPEXPCOMPLETECONFIRM), szRealString);
  1562. //
  1563. // The SetListViewToString function helpfully sets the background color to
  1564. // gray instead of the default (white). But we actually want it white, so
  1565. // let's reset it here.
  1566. //
  1567. ListView_SetBkColor(GetDlgItem(hwndDlg,IDC_IMPEXPCOMPLETECONFIRM), GetSysColor(COLOR_WINDOW));
  1568. ListView_SetTextBkColor(GetDlgItem(hwndDlg,IDC_IMPEXPCOMPLETECONFIRM), GetSysColor(COLOR_WINDOW));
  1569. PropSheet_SetWizButtons(hwndParent, PSWIZB_BACK|PSWIZB_FINISH);
  1570. }
  1571. break;
  1572. default:
  1573. PropSheet_SetWizButtons( hwndParent, PSWIZB_NEXT | PSWIZB_BACK );
  1574. break;
  1575. }
  1576. }
  1577. return TRUE ;
  1578. }
  1579. //*************************************************************
  1580. //
  1581. // Wizard97DlgProc
  1582. //
  1583. // Dialog proc for welcome and complete pages.
  1584. //
  1585. BOOL_PTR CALLBACK ImpExpUserDlg::Wizard97DlgProc
  1586. (
  1587. HWND hwndDlg,
  1588. UINT msg,
  1589. WPARAM wParam,
  1590. LPARAM lParam
  1591. )
  1592. {
  1593. ReturnValue retVal;
  1594. ImpExpUserProcess* m_pImpExp = NULL;
  1595. DWORD m_idPage = 0;
  1596. if( !CommonDialogProc( hwndDlg, msg, wParam, lParam,
  1597. &m_pImpExp, &m_idPage, retVal))
  1598. {
  1599. return retVal;
  1600. }
  1601. if( m_idPage == IDD_IMPEXPCOMPLETE
  1602. && msg == WM_NOTIFY
  1603. && PSN_WIZFINISH == ((LPNMHDR)lParam)->code)
  1604. m_pImpExp->PerformImpExpProcess(hwndDlg);
  1605. return retVal;;
  1606. }
  1607. //*************************************************************
  1608. //
  1609. // TransferTypeDlg
  1610. //
  1611. // Dialog proc for dialog where user picks transfer type
  1612. // (import vs. export), (cookies vs. bookmarks)
  1613. BOOL_PTR CALLBACK ImpExpUserDlg::TransferTypeDlg
  1614. (
  1615. HWND hwndDlg,
  1616. UINT msg,
  1617. WPARAM wParam,
  1618. LPARAM lParam
  1619. )
  1620. {
  1621. ReturnValue retVal;
  1622. ImpExpUserProcess* m_pImpExp = NULL;
  1623. DWORD m_idPage = 0;
  1624. if( !CommonDialogProc( hwndDlg, msg, wParam, lParam,
  1625. &m_pImpExp, &m_idPage, retVal))
  1626. {
  1627. return retVal;
  1628. }
  1629. HWND hwndDlgItem;
  1630. switch( msg)
  1631. {
  1632. case WM_INITDIALOG:
  1633. {
  1634. hwndDlgItem = GetDlgItem( hwndDlg, IDC_IMPEXPACTIONLISTBOX);
  1635. LRESULT index;
  1636. TCHAR szBuffer[MAX_PATH];
  1637. const DWORD cbSize = MAX_PATH;
  1638. if( MLLoadString( IDS_IMPFAVORITES, szBuffer, cbSize))
  1639. {
  1640. index = ListBox_AddString( hwndDlgItem, szBuffer);
  1641. ListBox_SetItemData( hwndDlgItem, index, IDS_IMPFAVORITES);
  1642. }
  1643. if( MLLoadString( IDS_EXPFAVORITES, szBuffer, cbSize))
  1644. {
  1645. index = ListBox_AddString( hwndDlgItem, szBuffer);
  1646. ListBox_SetItemData( hwndDlgItem, index, IDS_EXPFAVORITES);
  1647. }
  1648. if( MLLoadString( IDS_IMPCOOKIES, szBuffer, cbSize))
  1649. {
  1650. index = ListBox_AddString( hwndDlgItem, szBuffer);
  1651. ListBox_SetItemData( hwndDlgItem, index, IDS_IMPCOOKIES);
  1652. }
  1653. if( MLLoadString( IDS_EXPCOOKIES, szBuffer, cbSize))
  1654. {
  1655. index = ListBox_AddString( hwndDlgItem, szBuffer);
  1656. ListBox_SetItemData( hwndDlgItem, index, IDS_EXPCOOKIES);
  1657. }
  1658. // Select the first list item, by default
  1659. ListBox_SetCurSel(hwndDlgItem, 0);
  1660. HandleTransferTypeChange(hwndDlg, m_pImpExp, IDS_IMPFAVORITES);
  1661. } // end of WM_INITDIALOG
  1662. break;
  1663. case WM_COMMAND:
  1664. // when the user selects an option, choose it and
  1665. //and update the description box.
  1666. hwndDlgItem = GetDlgItem(hwndDlg, IDC_IMPEXPACTIONLISTBOX);
  1667. if(hwndDlgItem == (HWND)lParam
  1668. && HIWORD(wParam) == LBN_SELCHANGE)
  1669. {
  1670. // find out which string resource was selected.
  1671. LRESULT index = ListBox_GetCurSel(hwndDlgItem);
  1672. LRESULT selection = ListBox_GetItemData(hwndDlgItem, index);
  1673. HandleTransferTypeChange ( hwndDlg, m_pImpExp, (UINT)selection ) ;
  1674. retVal = TRUE;
  1675. }
  1676. break;
  1677. case WM_NOTIFY:
  1678. //
  1679. // Prevent advancement until user has made valid choices
  1680. //
  1681. if( ((LPNMHDR)lParam)->code == PSN_WIZNEXT && m_pImpExp
  1682. && (m_pImpExp->GetExternalType() == INVALID_EXTERNAL
  1683. || m_pImpExp->GetTransferType() == INVALID_TRANSFER))
  1684. {
  1685. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, -1);
  1686. retVal = TRUE;
  1687. }
  1688. //
  1689. // otherwise, set the filename to nul (so we get the default)
  1690. // and allow default navigation behavior
  1691. //
  1692. if (m_pImpExp)
  1693. m_pImpExp->m_szFileName[0] = TEXT('\0');
  1694. break;
  1695. }
  1696. return retVal;
  1697. }
  1698. void ImpExpUserDlg::HandleTransferTypeChange ( HWND hwndDlg, ImpExpUserProcess* pImpExp, UINT iSelect )
  1699. {
  1700. TCHAR szBuffer[MAX_PATH];
  1701. const DWORD cbSize = MAX_PATH;
  1702. if (pImpExp)
  1703. {
  1704. //
  1705. // Note: The description of each option has a resource id
  1706. // which is one higher than the resource id of the option name.
  1707. //
  1708. switch( iSelect )
  1709. {
  1710. case IDS_IMPFAVORITES:
  1711. if( MLLoadString( IDS_IMPFAVORITES + 1, szBuffer, cbSize ) )
  1712. SetWindowText( GetDlgItem( hwndDlg, IDC_IMPEXPACTIONDESCSTATIC ),
  1713. szBuffer );
  1714. pImpExp->SelectExternalType( BOOKMARKS );
  1715. pImpExp->SelectTransferType( IMPORT );
  1716. break;
  1717. case IDS_EXPFAVORITES:
  1718. if( MLLoadString( IDS_EXPFAVORITES + 1, szBuffer, cbSize ) )
  1719. SetWindowText( GetDlgItem( hwndDlg, IDC_IMPEXPACTIONDESCSTATIC ),
  1720. szBuffer );
  1721. pImpExp->SelectExternalType( BOOKMARKS );
  1722. pImpExp->SelectTransferType( EXPORT );
  1723. break;
  1724. case IDS_IMPCOOKIES:
  1725. if( MLLoadString( IDS_IMPCOOKIES + 1, szBuffer, cbSize))
  1726. SetWindowText( GetDlgItem( hwndDlg, IDC_IMPEXPACTIONDESCSTATIC),
  1727. szBuffer);
  1728. pImpExp->SelectExternalType( COOKIES);
  1729. pImpExp->SelectTransferType( IMPORT);
  1730. break;
  1731. case IDS_EXPCOOKIES:
  1732. if( MLLoadString( IDS_EXPCOOKIES + 1, szBuffer, cbSize))
  1733. SetWindowText( GetDlgItem( hwndDlg, IDC_IMPEXPACTIONDESCSTATIC),
  1734. szBuffer);
  1735. pImpExp->SelectExternalType( COOKIES);
  1736. pImpExp->SelectTransferType( EXPORT);
  1737. break;
  1738. }
  1739. }
  1740. }
  1741. //*************************************************************
  1742. //
  1743. // InternalDlg
  1744. //
  1745. // Allows user to pick internal target/source from tree view.
  1746. BOOL_PTR CALLBACK ImpExpUserDlg::InternalDlg
  1747. (
  1748. HWND hwndDlg,
  1749. UINT msg,
  1750. WPARAM wParam,
  1751. LPARAM lParam
  1752. )
  1753. {
  1754. ReturnValue retVal;
  1755. ImpExpUserProcess* m_pImpExp = NULL;
  1756. DWORD m_idPage = 0;
  1757. if( !CommonDialogProc( hwndDlg, msg, wParam, lParam,
  1758. &m_pImpExp, &m_idPage, retVal))
  1759. {
  1760. return retVal;
  1761. }
  1762. HWND hwndDlgItem;
  1763. switch( msg)
  1764. {
  1765. case WM_INITDIALOG:
  1766. //
  1767. // Populate the tree control
  1768. //
  1769. hwndDlgItem = GetDlgItem(hwndDlg, IDC_IMPEXPFAVTREE);
  1770. if ( hwndDlgItem )
  1771. {
  1772. if (m_pImpExp)
  1773. {
  1774. m_pImpExp->PopulateTreeViewForInternalSelection(hwndDlgItem);
  1775. m_pImpExp->ExpandTreeViewRoot ( hwndDlgItem ) ;
  1776. }
  1777. }
  1778. else
  1779. ASSERT(0);
  1780. return TRUE;
  1781. case WM_NOTIFY:
  1782. switch( ((LPNMHDR)lParam)->code)
  1783. {
  1784. case PSN_WIZNEXT:
  1785. // Only allow user to go to next if there is a valid selection.
  1786. if( !m_pImpExp->SelectInternalSelection(GetDlgItem(hwndDlg,IDC_IMPEXPFAVTREE)) )
  1787. {
  1788. SetWindowLongPtr( hwndDlg, DWLP_MSGRESULT, -1);
  1789. retVal = TRUE;
  1790. }
  1791. }
  1792. }
  1793. return retVal;
  1794. }
  1795. BOOL IsValidFileOrURL(LPTSTR szFileOrURL)
  1796. {
  1797. if (szFileOrURL == NULL)
  1798. return FALSE;
  1799. //
  1800. // any URL is ok
  1801. //
  1802. if (PathIsURL(szFileOrURL))
  1803. return TRUE;
  1804. //
  1805. // just a directory is no good, we need a filename too
  1806. //
  1807. if (PathIsDirectory(szFileOrURL))
  1808. return FALSE;
  1809. //
  1810. // just a filename is no good, we need a directory too
  1811. //
  1812. if (PathIsFileSpec(szFileOrURL))
  1813. return FALSE;
  1814. //
  1815. // relative paths are no good
  1816. //
  1817. if (PathIsRelative(szFileOrURL))
  1818. return FALSE;
  1819. //
  1820. // now make sure it parses correctly
  1821. //
  1822. if (PathFindFileName(szFileOrURL) == szFileOrURL)
  1823. return FALSE;
  1824. return TRUE;
  1825. }
  1826. //*************************************************************
  1827. //
  1828. // ExternalDlg
  1829. //
  1830. // Allows user to pick external target/source from list box
  1831. //or manual browse.
  1832. BOOL_PTR CALLBACK ImpExpUserDlg::ExternalDlg
  1833. (
  1834. HWND hwndDlg,
  1835. UINT msg,
  1836. WPARAM wParam,
  1837. LPARAM lParam
  1838. )
  1839. {
  1840. ReturnValue retVal;
  1841. ImpExpUserProcess* m_pImpExp = NULL;
  1842. DWORD m_idPage = 0;
  1843. if( !CommonDialogProc( hwndDlg, msg, wParam, lParam,
  1844. &m_pImpExp, &m_idPage, retVal))
  1845. {
  1846. return retVal;
  1847. }
  1848. HWND hwndDlgItem;
  1849. switch(msg)
  1850. {
  1851. case WM_COMMAND:
  1852. hwndDlgItem = (HWND) lParam;
  1853. if( HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_IMPEXPBROWSE)
  1854. {
  1855. OPENFILENAME ofn;
  1856. TCHAR szFile[MAX_PATH];
  1857. TCHAR szTitle[MAX_PATH];
  1858. TCHAR szFilter[MAX_PATH];
  1859. TCHAR szInitialPath[MAX_PATH];
  1860. int i;
  1861. ZeroMemory(&ofn, sizeof(OPENFILENAME));
  1862. ofn.lStructSize = sizeof(OPENFILENAME);
  1863. ofn.hwndOwner = hwndDlg;
  1864. ofn.hInstance = MLGetHinst();
  1865. ofn.lpstrFilter = szFilter;
  1866. ofn.nFilterIndex = 1;
  1867. ofn.lpstrCustomFilter = NULL;
  1868. ofn.lpstrFile = szFile;
  1869. ofn.nMaxFile = sizeof(szFile);
  1870. ofn.lpstrFileTitle = NULL;
  1871. ofn.lpstrInitialDir = szInitialPath;
  1872. ofn.lpstrTitle = szTitle;
  1873. ofn.lpstrDefExt = (m_pImpExp->GetExternalType()==COOKIES) ? TEXT("txt") : TEXT("htm");
  1874. GetDlgItemText(hwndDlg, IDC_IMPEXPMANUAL, szInitialPath, ARRAYSIZE(szFile));
  1875. szFile[0] = 0;
  1876. if (PathIsDirectory(szInitialPath))
  1877. {
  1878. ofn.lpstrInitialDir = szInitialPath;
  1879. szFile[0] = TEXT('\0');
  1880. }
  1881. else
  1882. {
  1883. TCHAR *pchFilePart;
  1884. pchFilePart = PathFindFileName(szInitialPath);
  1885. if (pchFilePart == szInitialPath || pchFilePart == NULL)
  1886. {
  1887. if (PathIsFileSpec(szInitialPath))
  1888. StrCpyN(szFile,szInitialPath,MAX_PATH);
  1889. else
  1890. szFile[0] = TEXT('\0');
  1891. ofn.lpstrInitialDir = szInitialPath;
  1892. SHGetSpecialFolderPath(NULL,szInitialPath,CSIDL_DESKTOP,FALSE);
  1893. }
  1894. else
  1895. {
  1896. pchFilePart[-1] = TEXT('\0');
  1897. ofn.lpstrInitialDir = szInitialPath;
  1898. StrCpyN(szFile,pchFilePart,MAX_PATH);
  1899. }
  1900. }
  1901. //
  1902. // Work out the title and the filter strings
  1903. //
  1904. if (m_pImpExp->GetExternalType() == BOOKMARKS)
  1905. {
  1906. MLLoadShellLangString(IDS_IMPEXP_CHOSEBOOKMARKFILE,szTitle,MAX_PATH);
  1907. MLLoadShellLangString(IDS_IMPEXP_BOOKMARKFILTER,szFilter,MAX_PATH);
  1908. }
  1909. else
  1910. {
  1911. MLLoadShellLangString(IDS_IMPEXP_CHOSECOOKIEFILE,szTitle,MAX_PATH);
  1912. MLLoadShellLangString(IDS_IMPEXP_COOKIEFILTER,szFilter,MAX_PATH);
  1913. }
  1914. //
  1915. // Search and replace '@' with nul in the filter string
  1916. //
  1917. for (i=0; szFilter[i]; i++)
  1918. if (szFilter[i]==TEXT('@'))
  1919. szFilter[i]=TEXT('\0');
  1920. //
  1921. // Set the flags for openfilename
  1922. //
  1923. ofn.Flags = OFN_EXPLORER | OFN_HIDEREADONLY ;
  1924. if (m_pImpExp->GetTransferType() == IMPORT)
  1925. ofn.Flags |= (OFN_HIDEREADONLY | OFN_PATHMUSTEXIST | OFN_FILEMUSTEXIST);
  1926. //
  1927. // Show the dialog
  1928. //
  1929. if(GetSaveFileName(&ofn))
  1930. if(SetWindowText(GetDlgItem(hwndDlg, IDC_IMPEXPMANUAL), ofn.lpstrFile))
  1931. {
  1932. Button_SetCheck(GetDlgItem( hwndDlg, IDC_IMPEXPRADIOFILE), BST_CHECKED);
  1933. Button_SetCheck(GetDlgItem( hwndDlg, IDC_IMPEXPRADIOAPP), BST_UNCHECKED);
  1934. }
  1935. retVal = TRUE;
  1936. }
  1937. break;
  1938. case WM_NOTIFY:
  1939. switch( ((LPNMHDR)lParam)->code )
  1940. {
  1941. case PSN_SETACTIVE:
  1942. {
  1943. TCHAR sBuffer[MAX_PATH];
  1944. DWORD cbSize = ARRAYSIZE(sBuffer);
  1945. hwndDlgItem = GetDlgItem( hwndDlg, IDC_IMPEXPEXTERNALCOMBO );
  1946. //
  1947. // Load the "application list" into the combo box.
  1948. // If the list is empty, then disable the combo box,
  1949. // disable the associated radio button, and select the
  1950. // "to/from file" option (the second radio button).
  1951. //
  1952. if( hwndDlgItem != NULL
  1953. && m_pImpExp && m_pImpExp->PopulateComboBoxForExternalSelection( hwndDlgItem ) )
  1954. {
  1955. EnableWindow ( GetDlgItem(hwndDlg, IDC_IMPEXPRADIOAPP), TRUE ) ;
  1956. EnableWindow ( hwndDlgItem, TRUE ) ;
  1957. Button_SetCheck( GetDlgItem( hwndDlg, IDC_IMPEXPRADIOAPP), BST_CHECKED);
  1958. Button_SetCheck( GetDlgItem( hwndDlg, IDC_IMPEXPRADIOFILE), BST_UNCHECKED);
  1959. }
  1960. else if ( hwndDlgItem != NULL)
  1961. {
  1962. EnableWindow ( GetDlgItem(hwndDlg, IDC_IMPEXPRADIOAPP), FALSE ) ;
  1963. EnableWindow( hwndDlgItem, FALSE ) ;
  1964. Button_SetCheck( GetDlgItem( hwndDlg, IDC_IMPEXPRADIOFILE), BST_CHECKED);
  1965. Button_SetCheck( GetDlgItem( hwndDlg, IDC_IMPEXPRADIOAPP), BST_UNCHECKED);
  1966. }
  1967. // Put a default value in the browse option.
  1968. if(m_pImpExp->GetExternalManualDefault(sBuffer, &cbSize))
  1969. SetDlgItemText(hwndDlg, IDC_IMPEXPMANUAL, sBuffer);
  1970. SHAutoComplete(GetDlgItem(hwndDlg, IDC_IMPEXPMANUAL), SHACF_FILESYSTEM);
  1971. }
  1972. break;
  1973. case PSN_WIZNEXT:
  1974. // If the application radio button is checked,
  1975. // select the selection from the application combo box. If
  1976. // the manual button is checked, select the selection
  1977. // using the manual edit box.
  1978. retVal = TRUE;
  1979. if (Button_GetCheck(GetDlgItem(hwndDlg,IDC_IMPEXPRADIOAPP)) == BST_CHECKED)
  1980. {
  1981. HWND hwndComboBox = GetDlgItem(hwndDlg,IDC_IMPEXPEXTERNALCOMBO);
  1982. if (hwndComboBox != NULL)
  1983. {
  1984. // Find out the index of the selected item
  1985. INT nIndex = ComboBox_GetCurSel(hwndDlg);
  1986. if (nIndex != CB_ERR)
  1987. {
  1988. // Retrieve a pointer to the filename
  1989. LPTSTR pszFileName = (LPTSTR)ComboBox_GetItemData(hwndComboBox, nIndex);
  1990. if (pszFileName != NULL)
  1991. StrCpyN(m_pImpExp->m_szFileName,pszFileName,MAX_PATH);
  1992. }
  1993. }
  1994. }
  1995. else if (Button_GetCheck(GetDlgItem(hwndDlg,IDC_IMPEXPRADIOFILE)) == BST_CHECKED)
  1996. {
  1997. // just get the text from the edit box
  1998. GetDlgItemText(hwndDlg,IDC_IMPEXPMANUAL,m_pImpExp->m_szFileName,MAX_PATH);
  1999. //
  2000. // Don't allow "next" if the edit control contains a bogus filename
  2001. //
  2002. if (!IsValidFileOrURL(m_pImpExp->m_szFileName))
  2003. {
  2004. TCHAR szFmt[128];
  2005. TCHAR szMsg[INTERNET_MAX_URL_LENGTH+128];
  2006. MLLoadShellLangString(IDS_INVALIDURLFILE, szFmt, ARRAYSIZE(szFmt));
  2007. wnsprintf(szMsg, INTERNET_MAX_URL_LENGTH+40, szFmt, m_pImpExp->m_szFileName);
  2008. MLShellMessageBox(
  2009. hwndDlg,
  2010. szMsg,
  2011. (IMPORT == m_pImpExp->GetTransferType()) ?
  2012. MAKEINTRESOURCE(IDS_CONFIRM_IMPTTL_FAV) :
  2013. MAKEINTRESOURCE(IDS_CONFIRM_EXPTTL_FAV),
  2014. MB_OK);
  2015. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
  2016. return retVal;
  2017. }
  2018. //
  2019. // If the user doesn't type an extension, then we add ".htm"
  2020. // or ".txt" as appropriate. Otherwise, we don't touch it.
  2021. //
  2022. if (*PathFindExtension(m_pImpExp->m_szFileName) == TEXT('\0'))
  2023. {
  2024. PathRenameExtension(
  2025. m_pImpExp->m_szFileName,
  2026. (m_pImpExp->GetExternalType()==COOKIES) ? TEXT(".txt") : TEXT(".htm"));
  2027. }
  2028. }
  2029. else
  2030. {
  2031. ASSERT(0);
  2032. m_pImpExp->m_szFileName[0] = TEXT('\0');
  2033. }
  2034. //
  2035. // Finally, show an overwrite or file-not-found message
  2036. // (but supress it if importing or exporting to a web address)
  2037. //
  2038. if (m_pImpExp->GetExternalType() == COOKIES ||
  2039. !PathIsURL(m_pImpExp->m_szFileName))
  2040. {
  2041. if ( EXPORT == m_pImpExp->GetTransferType() &&
  2042. GetFileAttributes(m_pImpExp->m_szFileName) != 0xFFFFFFFF )
  2043. {
  2044. int answer ;
  2045. UINT idTitle ;
  2046. if ( m_pImpExp->GetExternalType() == COOKIES )
  2047. idTitle = IDS_EXPCOOKIES ;
  2048. else if ( m_pImpExp->GetExternalType() == BOOKMARKS )
  2049. idTitle = IDS_EXPFAVORITES ;
  2050. else
  2051. ASSERT(0);
  2052. answer = WarningMessageBox(
  2053. hwndDlg,
  2054. idTitle,
  2055. IDS_IMPEXP_FILEEXISTS,
  2056. m_pImpExp->m_szFileName,
  2057. MB_YESNO | MB_ICONEXCLAMATION);
  2058. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, (IDYES==answer)?0:-1);
  2059. }
  2060. else
  2061. {
  2062. if (IMPORT == m_pImpExp->GetTransferType())
  2063. {
  2064. BOOL fError;
  2065. fError = FALSE;
  2066. if (PathIsUNC(m_pImpExp->m_szFileName))
  2067. ;
  2068. else
  2069. // Give the user a chance to insert the floppy if it's not already in.
  2070. fError = FAILED(SHPathPrepareForWriteWrap(hwndDlg,
  2071. NULL,
  2072. m_pImpExp->m_szFileName,
  2073. FO_COPY,
  2074. (SHPPFW_DEFAULT | SHPPFW_IGNOREFILENAME)));
  2075. if (!fError)
  2076. fError = (0xFFFFFFFF == GetFileAttributes(m_pImpExp->m_szFileName));
  2077. if (fError)
  2078. {
  2079. UINT idTitle ;
  2080. if ( m_pImpExp->GetExternalType() == COOKIES )
  2081. idTitle = IDS_IMPCOOKIES ;
  2082. else if ( m_pImpExp->GetExternalType() == BOOKMARKS )
  2083. idTitle = IDS_IMPFAVORITES ;
  2084. else
  2085. ASSERT(0);
  2086. WarningMessageBox(
  2087. hwndDlg,
  2088. idTitle,
  2089. IDS_IMPEXP_FILENOTFOUND,
  2090. m_pImpExp->m_szFileName,
  2091. MB_OK | MB_ICONEXCLAMATION);
  2092. SetWindowLongPtr(hwndDlg, DWLP_MSGRESULT, -1);
  2093. }
  2094. }
  2095. }
  2096. }
  2097. break; // PSN_WIZNEXT
  2098. } // WM_NOTIFY
  2099. break;
  2100. } // switch(msg)
  2101. return retVal;
  2102. }
  2103. BOOL WINAPI RunImportExportFavoritesWizard(HWND hDlg)
  2104. {
  2105. ImpExpUserDlg::RunNewDialogProcess(hDlg);
  2106. return TRUE;
  2107. }
  2108. int WarningMessageBox(HWND hwnd, UINT idTitle, UINT idMessage, LPCTSTR szFile, DWORD dwFlags)
  2109. {
  2110. TCHAR szBuffer[1024];
  2111. TCHAR szFormat[1024];
  2112. //
  2113. // load the string (must contain "%s")
  2114. //
  2115. MLLoadShellLangString(idMessage, szFormat, 1024);
  2116. //
  2117. // insert the filename
  2118. //
  2119. wnsprintf(szBuffer,1024,szFormat,szFile);
  2120. //
  2121. // display the messagebox
  2122. //
  2123. return MLShellMessageBox(
  2124. hwnd,
  2125. szBuffer,
  2126. MAKEINTRESOURCE(idTitle),
  2127. dwFlags);
  2128. }