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.

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