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.

749 lines
20 KiB

  1. #include "pch.hxx"
  2. #include "impapi.h"
  3. #include "comconv.h"
  4. #include <newimp.h>
  5. #include <eudrimp.h>
  6. #include "commimp.h"
  7. #include <mapi.h>
  8. #include <mapix.h>
  9. #include <import.h>
  10. #include <dllmain.h>
  11. ASSERTDATA
  12. HRESULT FindSnm(EUDORANODE *pParent, EUDORANODE **pplist, TCHAR *npath);
  13. INT_PTR CALLBACK SelectCommUserDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  14. HRESULT GetCommunicatorDirectory(char *szUser, char *szDir, int cch);
  15. const static char c_szSnmExt[] = "\\*.snm";
  16. const static char c_szSnmHeader[] = "# Netscape folder cache"; //used for avoiding processing Netscape 3.0 SNM files
  17. const static char c_szDrafts[] = "Drafts";
  18. const static char c_szUnsent[] = "Unsent Messages";
  19. const static char c_szSent[] = "Sent";
  20. CCommunicatorImport::CCommunicatorImport()
  21. {
  22. DllAddRef();
  23. m_cRef = 1;
  24. m_plist = NULL;
  25. *m_szUser = 0;
  26. }
  27. CCommunicatorImport::~CCommunicatorImport()
  28. {
  29. if (m_plist != NULL)
  30. EudoraFreeFolderList(m_plist);
  31. DllRelease();
  32. }
  33. ULONG CCommunicatorImport::AddRef()
  34. {
  35. m_cRef++;
  36. return(m_cRef);
  37. }
  38. ULONG CCommunicatorImport::Release()
  39. {
  40. ULONG cRef;
  41. cRef = --m_cRef;
  42. if (cRef == 0)
  43. delete this;
  44. return(cRef);
  45. }
  46. HRESULT CCommunicatorImport::QueryInterface(REFIID riid, LPVOID *ppv)
  47. {
  48. HRESULT hr = S_OK;
  49. if (ppv == NULL)
  50. return(E_INVALIDARG);
  51. *ppv = NULL;
  52. if (IID_IMailImport == riid)
  53. *ppv = (IMailImport *)this;
  54. else if (IID_IUnknown == riid)
  55. *ppv = (IUnknown *)this;
  56. else
  57. hr = E_NOINTERFACE;
  58. if (*ppv != NULL)
  59. ((LPUNKNOWN)*ppv)->AddRef();
  60. return(hr);
  61. }
  62. typedef struct tagSELCOMMINFO
  63. {
  64. char szUser[MAX_PATH];
  65. HKEY hkey;
  66. } SELCOMMINFO;
  67. const static char c_szRegNscp[] = "Software\\Netscape\\Netscape Navigator\\Users";
  68. HRESULT CCommunicatorImport::InitializeImport(HWND hwnd)
  69. {
  70. DWORD cUsers;
  71. int iRet;
  72. HKEY hkey;
  73. HRESULT hr;
  74. SELCOMMINFO si;
  75. hr = S_OK;
  76. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegNscp, 0, KEY_ALL_ACCESS, &hkey))
  77. {
  78. if (ERROR_SUCCESS == RegQueryInfoKey(hkey, NULL, NULL, 0, &cUsers, NULL, NULL, NULL, NULL, NULL, NULL, NULL))
  79. {
  80. if (cUsers > 1)
  81. {
  82. si.hkey = hkey;
  83. iRet = (int) DialogBoxParam(g_hInstImp, MAKEINTRESOURCE(iddSelectCommUser), hwnd, SelectCommUserDlgProc, (LPARAM)&si);
  84. if (iRet == IDCANCEL)
  85. hr = S_FALSE;
  86. else if (iRet == IDOK)
  87. StrCpyN(m_szUser, si.szUser, ARRAYSIZE(m_szUser));
  88. else
  89. hr = E_FAIL;
  90. }
  91. }
  92. RegCloseKey(hkey);
  93. }
  94. return(hr);
  95. }
  96. INT_PTR CALLBACK SelectCommUserDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  97. {
  98. HWND hwndT;
  99. WORD id;
  100. DWORD iSubKey, cb;
  101. char sz[MAX_PATH];
  102. SELCOMMINFO *psi;
  103. int index;
  104. switch (msg)
  105. {
  106. case WM_INITDIALOG:
  107. Assert(lParam != NULL);
  108. psi = (SELCOMMINFO *)lParam;
  109. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LONG_PTR)psi);
  110. hwndT = GetDlgItem(hwnd, IDC_USERLIST);
  111. // fill list
  112. iSubKey = 0;
  113. cb = sizeof(sz);
  114. while (ERROR_SUCCESS == RegEnumKeyEx(psi->hkey, iSubKey, sz, &cb, NULL, NULL, NULL, NULL))
  115. {
  116. SendMessage(hwndT, LB_ADDSTRING, 0, (LPARAM)sz);
  117. iSubKey++;
  118. cb = sizeof(sz);
  119. }
  120. SendMessage(hwndT, LB_SETCURSEL, 0, 0);
  121. return(TRUE);
  122. case WM_COMMAND:
  123. id = LOWORD(wParam);
  124. switch (id)
  125. {
  126. case IDOK:
  127. psi = (SELCOMMINFO *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  128. Assert(psi != NULL);
  129. hwndT = GetDlgItem(hwnd, IDC_USERLIST);
  130. index = (int) SendMessage(hwndT, LB_GETCURSEL, 0, 0);
  131. Assert(index >= 0);
  132. if (SendMessage(hwndT, LB_GETTEXTLEN, (WPARAM)index, 0) < ARRAYSIZE(psi->szUser))
  133. SendMessage(hwndT, LB_GETTEXT, (WPARAM)index, (LPARAM)psi->szUser);
  134. // fall through
  135. case IDCANCEL:
  136. EndDialog(hwnd, id);
  137. return(TRUE);
  138. }
  139. break;
  140. }
  141. return(FALSE);
  142. }
  143. const static char c_szCommunicatorKey[] = "SOFTWARE\\Netscape\\Netscape Navigator\\Users";
  144. const static char c_szCurrentUser[] = "CurrentUser";
  145. const static char c_szDirRoot[] = "DirRoot";
  146. const static char c_szMailDir[] = "\\Mail";
  147. HRESULT GetCommunicatorDirectory(char *szUser, char *szDir, int cch)
  148. {
  149. char sz[MAX_PATH], szTemp[MAX_PATH], szExpanded[MAX_PATH], *psz;
  150. HKEY hkResult, hkResult1;
  151. LONG lRes;
  152. DWORD cb, dwType;
  153. HRESULT hr;
  154. hr = E_FAIL;
  155. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szCommunicatorKey, 0, KEY_QUERY_VALUE, &hkResult))
  156. {
  157. if (szUser == NULL)
  158. {
  159. cb = sizeof(sz);
  160. lRes = RegQueryValueEx(hkResult, c_szCurrentUser, NULL, NULL, (LPBYTE)sz, &cb);
  161. szUser = sz;
  162. }
  163. else
  164. {
  165. Assert(*szUser != 0);
  166. lRes = ERROR_SUCCESS;
  167. }
  168. if (lRes == ERROR_SUCCESS)
  169. {
  170. cb = sizeof(szTemp);
  171. if (ERROR_SUCCESS == RegOpenKeyEx(hkResult, szUser, 0, KEY_QUERY_VALUE, &hkResult1))
  172. {
  173. if (ERROR_SUCCESS == RegQueryValueEx(hkResult1, c_szDirRoot, NULL, &dwType, (LPBYTE)szTemp, &cb))
  174. {
  175. if (REG_EXPAND_SZ == dwType)
  176. {
  177. ZeroMemory(szExpanded, ARRAYSIZE(szExpanded));
  178. ExpandEnvironmentStrings(szTemp, szExpanded, ARRAYSIZE(szExpanded));
  179. psz = szExpanded;
  180. }
  181. else
  182. psz = szTemp;
  183. if (!GetStorePath(psz, szDir, cch))
  184. {
  185. StrCpyN(szDir, psz, cch);
  186. StrCatBuff(szDir, c_szMailDir, cch);
  187. }
  188. hr = S_OK;
  189. }
  190. RegCloseKey(hkResult1);
  191. }
  192. }
  193. RegCloseKey(hkResult);
  194. }
  195. return(hr);
  196. }
  197. HRESULT CCommunicatorImport::GetDirectory(char *szDir, UINT cch)
  198. {
  199. HRESULT hr;
  200. Assert(szDir != NULL);
  201. hr = GetCommunicatorDirectory(*m_szUser != 0 ? m_szUser : NULL, szDir, cch);
  202. if (FAILED(hr))
  203. *szDir = 0;
  204. return(S_OK);
  205. }
  206. HRESULT CCommunicatorImport::SetDirectory(char *szDir)
  207. {
  208. HRESULT hr;
  209. Assert(szDir != NULL);
  210. if (!ValidStoreDirectory(szDir, NETSCAPE))
  211. return(S_FALSE);
  212. if (m_plist != NULL)
  213. {
  214. EudoraFreeFolderList(m_plist);
  215. m_plist = NULL;
  216. }
  217. hr = FindSnm(NULL, &m_plist, szDir);
  218. return(hr);
  219. }
  220. HRESULT CCommunicatorImport::EnumerateFolders(DWORD_PTR dwCookie, IEnumFOLDERS **ppEnum)
  221. {
  222. CCommunicatorEnumFOLDERS *pEnum;
  223. EUDORANODE *pnode;
  224. Assert(ppEnum != NULL);
  225. *ppEnum = NULL;
  226. if (dwCookie == COOKIE_ROOT)
  227. pnode = m_plist;
  228. else
  229. pnode = ((EUDORANODE *)dwCookie)->pchild;
  230. if (pnode == NULL)
  231. return(S_FALSE);
  232. pEnum = new CCommunicatorEnumFOLDERS(pnode);
  233. if (pEnum == NULL)
  234. return(E_OUTOFMEMORY);
  235. *ppEnum = pEnum;
  236. return(S_OK);
  237. }
  238. STDMETHODIMP CCommunicatorImport::ImportFolder(DWORD_PTR dwCookie, IFolderImport *pImport)
  239. {
  240. char szHdr[64];
  241. EUDORANODE *pnode;
  242. HRESULT hr = E_FAIL;
  243. TCHAR cMsgFile[MAX_PATH];
  244. BYTE *pSnm, *pMsg, *pEnd, *pEndMsg, *pT, *pNextMsg, *pLast;
  245. ULONG i, lMsgs, lTotalMsgs, lNumNulls, cbMsg, cbSnm, cExtra, uOffset, uMsgSize, cMsgImp;
  246. ULONG lRoof = 32;
  247. ULONG Offset = 0;
  248. int nNumLevels = 1;
  249. HANDLE mapSnm, mapMsg, hSnm, hMsg;
  250. Assert(pImport != NULL);
  251. pnode = (EUDORANODE *)dwCookie;
  252. Assert(pnode != NULL);
  253. if (pnode->iFileType == SNM_DRAFT)
  254. m_bDraft = TRUE;
  255. else
  256. m_bDraft = FALSE;
  257. Assert((pnode->iFileType == SNM_FILE ) || (pnode->iFileType == SNM_DRAFT));
  258. hr = E_FAIL;
  259. pSnm = NULL;
  260. mapSnm = NULL;
  261. pMsg = NULL;
  262. mapMsg = NULL;
  263. StrCpyN(cMsgFile, pnode->szFile, ARRAYSIZE(cMsgFile));
  264. cMsgFile[(lstrlen(cMsgFile)) - 4] = 0;
  265. hMsg = CreateFile(cMsgFile, GENERIC_READ, FILE_SHARE_READ, NULL,
  266. OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  267. if (hMsg == INVALID_HANDLE_VALUE)
  268. return(hrFolderOpenFail);
  269. cbMsg = GetFileSize(hMsg, NULL);
  270. if (cbMsg == 0)
  271. {
  272. CloseHandle(hMsg);
  273. return(S_OK);
  274. }
  275. hSnm = CreateFile(pnode->szFile, GENERIC_READ, FILE_SHARE_READ, NULL,
  276. OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, NULL);
  277. if (hSnm == INVALID_HANDLE_VALUE)
  278. {
  279. CloseHandle(hMsg);
  280. return(hrFolderOpenFail);
  281. }
  282. cbSnm = GetFileSize(hSnm, NULL);
  283. if (cbSnm < 2560)
  284. {
  285. // the .snm file header is 2560 bytes in size, so anything less
  286. // than this is bogus or doesn't have messages anyway, so no point
  287. // in continuing
  288. goto DoneImport;
  289. }
  290. mapSnm = CreateFileMapping(hSnm, NULL, PAGE_READONLY, 0, 0, NULL);
  291. if (mapSnm == NULL)
  292. goto DoneImport;
  293. pSnm = (BYTE *)MapViewOfFile(mapSnm, FILE_MAP_READ, 0, 0, 0);
  294. if (pSnm == NULL)
  295. goto DoneImport;
  296. pEnd = pSnm + cbSnm;
  297. // Do something else to verify the genuineness of the SNM file (like
  298. // comparing the two separately stored values of "total # of messages").
  299. // 1) Confirm that this is not a NS 3.0 SNM file.
  300. CopyMemory(szHdr, pSnm, ARRAYSIZE(c_szSnmHeader) - 1);
  301. szHdr[ARRAYSIZE(c_szSnmHeader) - 1] = 0;
  302. if (0 == lstrcmp(szHdr, c_szSnmHeader))
  303. {
  304. // this is a Version 3.0 SNM file
  305. goto DoneImport;
  306. }
  307. // 2) Do someting else!!! We need to verify as much as possible or we'll
  308. // end up hanging.
  309. mapMsg = CreateFileMapping(hMsg, NULL, PAGE_READONLY, 0, 0, NULL);
  310. if (mapMsg == NULL)
  311. goto DoneImport;
  312. pMsg = (BYTE *)MapViewOfFile(mapMsg, FILE_MAP_READ, 0, 0, 0);
  313. if (pMsg == NULL)
  314. goto DoneImport;
  315. pEndMsg = pMsg + cbMsg;
  316. // Get the total number of messages in the SNM file
  317. lTotalMsgs = GetOffset(pSnm, cbSnm, 400, 0); //408 - 8 as we add 8 in GetOffset
  318. cMsgImp = 0;
  319. pLast = pMsg;
  320. pImport->SetMessageCount(lTotalMsgs);
  321. if (lTotalMsgs > 0)
  322. {
  323. Offset = (ULONG)GetPrimaryOffset(pSnm, cbSnm);
  324. // Find the number of 'Levels'
  325. if(Offset < cbSnm)
  326. {
  327. while(lRoof < lTotalMsgs)
  328. {
  329. lRoof *= 32;
  330. nNumLevels++;
  331. }
  332. hr = ProcessBlocks(pSnm, cbSnm, pMsg, cbMsg, nNumLevels, Offset, pImport);
  333. }
  334. }
  335. DoneImport:
  336. if (pSnm != NULL)
  337. UnmapViewOfFile(pSnm);
  338. if (mapSnm != NULL)
  339. CloseHandle(mapSnm);
  340. if (pMsg != NULL)
  341. UnmapViewOfFile(pMsg);
  342. if (mapMsg != NULL)
  343. CloseHandle(mapMsg);
  344. CloseHandle(hSnm);
  345. CloseHandle(hMsg);
  346. return(hr);
  347. }
  348. HRESULT CCommunicatorImport::ProcessBlocks(BYTE* pSnm, ULONG cbSnm,
  349. BYTE* pMsg, ULONG cbMsg,
  350. int nLayer, ULONG Offset,
  351. IFolderImport *pImport)
  352. {
  353. HRESULT hr = S_OK;
  354. HRESULT hr1 = E_FAIL;
  355. Assert(Offset + 7 < cbSnm);
  356. int nNumLoops = (int)pSnm[Offset + 7];
  357. ULONG NewOffset = 0;
  358. for(int nElement = 0; nElement < nNumLoops; nElement++)
  359. {
  360. if(hr != hrUserCancel)
  361. {
  362. if(nLayer == 1)
  363. {
  364. NewOffset = GetOffset(pSnm, cbSnm, Offset, 2*nElement);
  365. // We use 2*nElement above to access elements 8 bytes apart.
  366. hr1 = ProcessMessages(pSnm,cbSnm, pMsg, cbMsg, NewOffset, pImport);
  367. if(FAILED(hr1))
  368. hr = E_FAIL;
  369. if(hr1 == hrUserCancel)
  370. return hr1;
  371. }
  372. else
  373. {
  374. NewOffset = GetOffset(pSnm, cbSnm, Offset, nElement);
  375. hr = ProcessBlocks(pSnm, cbSnm, pMsg, cbMsg, nLayer - 1, NewOffset, pImport);
  376. }
  377. }
  378. else
  379. return(hrUserCancel);
  380. }
  381. return(hr);
  382. }
  383. ULONG CCommunicatorImport::GetPrimaryOffset(BYTE* pSnm, ULONG cbSnm)
  384. {
  385. return GetOffset(pSnm, cbSnm, 416, 0); //424 - 8 as we add 8 in GetOffset
  386. }
  387. ULONG CCommunicatorImport::GetOffset(BYTE* pSnm, ULONG cbSnm, ULONG Offset, int nElement)
  388. {
  389. Assert (3 + Offset + (4*(nElement + 2)) < cbSnm); // One common check point!!!
  390. ULONG result = 0;
  391. result = (ULONG)pSnm[0 + Offset + (4*(nElement + 2))]*16777216 +
  392. (ULONG)pSnm[1 + Offset + (4*(nElement + 2))]*65536 +
  393. (ULONG)pSnm[2 + Offset + (4*(nElement + 2))]*256 +
  394. (ULONG)pSnm[3 + Offset + (4*(nElement + 2))];
  395. return result;
  396. }
  397. HRESULT CCommunicatorImport::ProcessMessages(BYTE* pSnm, ULONG cbSnm,
  398. BYTE* pMsg, ULONG cbMsg,
  399. ULONG NewOffset,
  400. IFolderImport* pImport)
  401. {
  402. ULONG lMsgOffset = 0;
  403. ULONG uMsgSize = 0;
  404. HRESULT hr = E_FAIL;
  405. LPSTREAM lpstm = NULL;
  406. int nPriority = 1;
  407. DWORD dwFlags = 0;
  408. nPriority = (int)*(pSnm + NewOffset + 47);
  409. switch(nPriority)
  410. {
  411. case 1:
  412. case 4:
  413. dwFlags |= MSG_PRI_NORMAL;
  414. break;
  415. case 2:
  416. case 3:
  417. dwFlags |= MSG_PRI_LOW;
  418. break;
  419. case 5:
  420. case 6:
  421. dwFlags |= MSG_PRI_HIGH;
  422. break;
  423. default:
  424. dwFlags |= MSG_PRI_NORMAL;
  425. break;
  426. }
  427. lMsgOffset = GetOffset(pSnm, cbSnm, NewOffset + 18, 0); //26 - 8 as we add 8 in GetOffset
  428. uMsgSize = GetOffset(pSnm, cbSnm, NewOffset + 40, 0); //48 - 8 as we add 8 in GetOffset
  429. Assert(lMsgOffset + uMsgSize <= cbMsg);
  430. Assert(pImport != NULL);
  431. hr = HrByteToStream(&lpstm, pMsg + lMsgOffset, uMsgSize);
  432. if (SUCCEEDED(hr))
  433. {
  434. Assert(lpstm != NULL);
  435. // 0x01 == read
  436. if (((pSnm + NewOffset) != NULL) && (0 == ((pSnm + NewOffset)[45] & 0x01)))
  437. dwFlags |= MSG_STATE_UNREAD;
  438. if(m_bDraft)
  439. dwFlags |= MSG_STATE_UNSENT;
  440. hr = pImport->ImportMessage(MSG_TYPE_MAIL, dwFlags, lpstm, NULL, 0);
  441. lpstm->Release();
  442. }
  443. return hr;
  444. }
  445. CCommunicatorEnumFOLDERS::CCommunicatorEnumFOLDERS(EUDORANODE *plist)
  446. {
  447. Assert(plist != NULL);
  448. m_cRef = 1;
  449. m_plist = plist;
  450. m_pnext = plist;
  451. }
  452. CCommunicatorEnumFOLDERS::~CCommunicatorEnumFOLDERS()
  453. {
  454. }
  455. ULONG CCommunicatorEnumFOLDERS::AddRef()
  456. {
  457. m_cRef++;
  458. return(m_cRef);
  459. }
  460. ULONG CCommunicatorEnumFOLDERS::Release()
  461. {
  462. ULONG cRef;
  463. cRef = --m_cRef;
  464. if (cRef == 0)
  465. delete this;
  466. return(cRef);
  467. }
  468. HRESULT CCommunicatorEnumFOLDERS::QueryInterface(REFIID riid, LPVOID *ppv)
  469. {
  470. HRESULT hr = S_OK;
  471. if (ppv == NULL)
  472. return(E_INVALIDARG);
  473. *ppv = NULL;
  474. if (IID_IEnumFOLDERS == riid)
  475. *ppv = (IEnumFOLDERS *)this;
  476. else if (IID_IUnknown == riid)
  477. *ppv = (IUnknown *)this;
  478. else
  479. hr = E_NOINTERFACE;
  480. if (*ppv != NULL)
  481. ((LPUNKNOWN)*ppv)->AddRef();
  482. return(hr);
  483. }
  484. HRESULT CCommunicatorEnumFOLDERS::Next(IMPORTFOLDER *pfldr)
  485. {
  486. Assert(pfldr != NULL);
  487. if (m_pnext == NULL)
  488. return(S_FALSE);
  489. ZeroMemory(pfldr, sizeof(IMPORTFOLDER));
  490. pfldr->dwCookie = (DWORD_PTR)m_pnext;
  491. // To map Netscape's "Sent" folder to OE's "Sent Items" - Bug 2688.
  492. if (m_pnext->type != FOLDER_TYPE_SENT)
  493. StrCpyN(pfldr->szName, m_pnext->szName, ARRAYSIZE(pfldr->szName));
  494. else
  495. StrCpyN(pfldr->szName, "Sent Items", ARRAYSIZE(pfldr->szName));
  496. pfldr->type = m_pnext->type;
  497. pfldr->fSubFolders = (m_pnext->pchild != NULL);
  498. m_pnext = m_pnext->pnext;
  499. return(S_OK);
  500. }
  501. HRESULT CCommunicatorEnumFOLDERS::Reset()
  502. {
  503. m_pnext = m_plist;
  504. return(S_OK);
  505. }
  506. /*******************************************************************
  507. * FUNCTION NAME:FindSnm
  508. *
  509. * PURPOSE:To Get the Snm files in a folder
  510. *
  511. * PARAMETERS:
  512. *
  513. * IN:parent EUDORANODE ,previously processed EUDORANODE
  514. *
  515. * OUT: Pointer to the first node in the tree
  516. *
  517. * RETURNS: TRUE or FALSE
  518. *******************************************************************/
  519. HRESULT FindSnm(EUDORANODE *pparent, EUDORANODE **pplist,TCHAR *npath)
  520. {
  521. HRESULT hr;
  522. HANDLE h1, h2;
  523. TCHAR path[MAX_PATH], path1[MAX_PATH], szInbox[CCHMAX_STRINGRES], szTrash[CCHMAX_STRINGRES];
  524. TCHAR szNewPath[MAX_PATH];
  525. WIN32_FIND_DATA FindFileData;
  526. WIN32_FIND_DATA SbdFileData;
  527. EUDORANODE *newp, *newp1, *last = NULL, *plist = NULL;
  528. Assert(pplist != NULL);
  529. Assert(npath != NULL);
  530. *pplist = NULL;
  531. StrCpyN(path, npath, ARRAYSIZE(path));
  532. StrCatBuff(path, c_szSnmExt, ARRAYSIZE(path));
  533. h1 = FindFirstFile(path, &FindFileData);
  534. if (h1 == INVALID_HANDLE_VALUE)
  535. return(S_OK);
  536. hr = E_OUTOFMEMORY;
  537. LoadString(g_hInstImp, idsInbox, szInbox, ARRAYSIZE(szInbox));
  538. LoadString(g_hInstImp, idsTrash, szTrash, ARRAYSIZE(szTrash));
  539. do
  540. {
  541. if (!MemAlloc((void **)&newp, sizeof(EUDORANODE)))
  542. goto err;
  543. ZeroMemory(newp, sizeof(EUDORANODE));
  544. if (plist == NULL)
  545. {
  546. Assert(last == NULL);
  547. plist = newp;
  548. }
  549. else
  550. {
  551. last->pnext = newp;
  552. }
  553. last = newp;
  554. StrCpyN(newp->szName, FindFileData.cFileName, ARRAYSIZE(newp->szName));
  555. wnsprintf(newp->szFile, ARRAYSIZE(newp->szFile), "%s\\%s", npath, newp->szName);
  556. newp->szName[(lstrlen(newp->szName)) - 4] = 0;
  557. if (0 == lstrcmpi(newp->szName, szInbox))
  558. newp->type = FOLDER_TYPE_INBOX;
  559. else if (0 == lstrcmpi(newp->szName, szTrash))
  560. newp->type = FOLDER_TYPE_DELETED;
  561. else if(0 == lstrcmpi(newp->szName, c_szSent)) //c_szSent need not be localised as per my investigation - v-sramas.
  562. newp->type = FOLDER_TYPE_SENT;
  563. newp->pparent = pparent;
  564. newp->depth = (pparent == NULL ? 0 : (pparent->depth + 1));
  565. // This following will be used later to set the flag of
  566. // a message so that it is editable (MSG_STATE_UNSENT).
  567. if ((0 == lstrcmpi(newp->szName, c_szDrafts)) ||(0 == lstrcmpi(newp->szName, c_szUnsent)))
  568. newp->iFileType = SNM_DRAFT;
  569. else
  570. newp->iFileType = SNM_FILE;
  571. // Search for a corresponding .SBD folder - file now.
  572. wnsprintf(path1, ARRAYSIZE(path1), "%s", newp->szFile);
  573. path1[(lstrlen(path1)) - 3] = 0;
  574. StrCatBuff(path1, "sbd", ARRAYSIZE(path1));
  575. h2 = FindFirstFile(path1, &SbdFileData);
  576. if (h2 != INVALID_HANDLE_VALUE)
  577. {
  578. //Recurse here
  579. wnsprintf(szNewPath, ARRAYSIZE(szNewPath), "%s\\%s", npath, SbdFileData.cFileName);
  580. FindSnm(newp, &newp->pchild, szNewPath);
  581. }
  582. }
  583. while (FindNextFile(h1, &FindFileData));
  584. hr = S_OK;
  585. err:
  586. FindClose(h1);
  587. if (FAILED(hr) && plist != NULL)
  588. {
  589. EudoraFreeFolderList(plist);
  590. plist = NULL;
  591. }
  592. *pplist = plist;
  593. return(hr);
  594. }