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.

411 lines
12 KiB

  1. #include <pch.hxx>
  2. #include "resource.h"
  3. #include "dllmain.h"
  4. #include "saveatt.h"
  5. #include "mimeolep.h"
  6. #include "demand.h"
  7. #include "msoert.h"
  8. #include "util.h"
  9. #include "shlwapi.h"
  10. #include "shlwapip.h"
  11. class CSaveAttachDlg
  12. {
  13. public:
  14. CSaveAttachDlg();
  15. ~CSaveAttachDlg();
  16. ULONG AddRef();
  17. ULONG Release();
  18. HRESULT Show(HWND hwndOwner, IMimeMessage *pMsg, LPWSTR rgchPath, ULONG cchPath, BOOL fShowUnsafe);
  19. static INT_PTR CALLBACK ExtDlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  20. private:
  21. ULONG m_cRef;
  22. IMimeMessage *m_pMsg;
  23. HWND m_hwnd,
  24. m_hwndList,
  25. m_hwndEdit;
  26. WCHAR m_rgchPath[MAX_PATH];
  27. BOOL m_fShowUnsafe;
  28. INT_PTR DlgProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam);
  29. HRESULT OnInitDialog(HWND hwnd);
  30. HRESULT OnDestroy();
  31. HRESULT OnWMNotfiy(WPARAM wParam, LPARAM lParam);
  32. HRESULT OnSave();
  33. HRESULT SaveAttachment(LPWSTR lpszDir, LPATTACHDATA pAttach);
  34. };
  35. CSaveAttachDlg::CSaveAttachDlg()
  36. {
  37. m_cRef = 1;
  38. *m_rgchPath = 0;
  39. m_hwnd = NULL;
  40. m_hwndList = NULL;
  41. m_hwndEdit = NULL;
  42. m_fShowUnsafe = FALSE;
  43. }
  44. CSaveAttachDlg::~CSaveAttachDlg()
  45. {
  46. }
  47. ULONG CSaveAttachDlg::AddRef()
  48. {
  49. return ++m_cRef;
  50. }
  51. ULONG CSaveAttachDlg::Release()
  52. {
  53. m_cRef--;
  54. if (m_cRef==0)
  55. {
  56. delete this;
  57. return 0;
  58. }
  59. return m_cRef;
  60. }
  61. HRESULT CSaveAttachDlg::Show(HWND hwndOwner, IMimeMessage *pMsg, LPWSTR lpszPath, ULONG cchPath, BOOL fShowUnsafe)
  62. {
  63. HRESULT hr;
  64. // no need to addref as it's a modal-dialog
  65. m_pMsg = pMsg;
  66. m_fShowUnsafe = fShowUnsafe;
  67. if (!PathFileExistsW(lpszPath) || !PathIsDirectoryW(lpszPath))
  68. HrGetLastOpenFileDirectoryW(ARRAYSIZE(m_rgchPath), m_rgchPath);
  69. else
  70. {
  71. Assert (cchPath <= MAX_PATH);
  72. StrCpyNW(m_rgchPath, lpszPath, ARRAYSIZE(m_rgchPath));
  73. }
  74. // save attachment DialogBox reutrn hresult
  75. hr =(HRESULT) DialogBoxParamWrapW(g_hLocRes, MAKEINTRESOURCEW(iddSaveAttachments), hwndOwner, ExtDlgProc, (LPARAM)this);
  76. if (lpszPath)
  77. StrCpyNW(lpszPath, m_rgchPath, cchPath);
  78. return hr;
  79. }
  80. HRESULT CSaveAttachDlg::OnSave()
  81. {
  82. HWND hwndEdit;
  83. LV_ITEMW lvi;
  84. int cItems,
  85. i;
  86. LPATTACHDATA pAttach;
  87. WCHAR wszDir[MAX_PATH+1],
  88. wszErr[MAX_PATH + CCHMAX_STRINGRES],
  89. wszFmt[CCHMAX_STRINGRES];
  90. HCURSOR hcur;
  91. HRESULT hr = S_OK;
  92. BOOL fFailures=FALSE;
  93. wszDir[MAX_PATH] = 0;
  94. hwndEdit = GetDlgItem(m_hwnd, idcPathEdit);
  95. AssertSz(hwndEdit, "Should have gotten an hwndEdit");
  96. GetWindowTextWrapW(hwndEdit, wszDir, MAX_PATH);
  97. if (!PathIsDirectoryW(wszDir))
  98. {
  99. LoadStringWrapW(g_hLocRes, idsErrFolderInvalid, wszFmt, ARRAYSIZE(wszFmt));
  100. wnsprintfW(wszErr, ARRAYSIZE(wszErr), wszFmt, wszDir);
  101. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsSaveAttachments), wszErr, NULL, MB_OK|MB_ICONEXCLAMATION);
  102. return E_FAIL;
  103. }
  104. hcur = SetCursor(LoadCursor(NULL, IDC_WAIT));
  105. cItems = ListView_GetItemCount(m_hwndList);
  106. ZeroMemory(&lvi, sizeof(lvi));
  107. lvi.mask = LVIF_STATE|LVIF_PARAM;
  108. lvi.stateMask = LVIS_SELECTED;
  109. for (i = 0; i < cItems; i++)
  110. {
  111. lvi.iItem = i;
  112. SendMessage(m_hwndList, LVM_GETITEMW, 0, (LPARAM)(LV_ITEMW*)(&lvi));
  113. if (lvi.state & LVIS_SELECTED)
  114. {
  115. pAttach = (LPATTACHDATA)lvi.lParam;
  116. hr = SaveAttachment(wszDir, pAttach);
  117. if (hr == MIMEEDIT_E_USERCANCEL)
  118. break;
  119. if (FAILED(hr))
  120. fFailures=TRUE; // flag error, but keep trying
  121. }
  122. }
  123. if (hcur)
  124. SetCursor(hcur);
  125. if (fFailures)
  126. AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsSaveAttachments), MAKEINTRESOURCEW(idsErrOneOrMoreAttachSaveFailed), NULL, MB_OK|MB_ICONEXCLAMATION);
  127. StrCpyNW(m_rgchPath, wszDir, MAX_PATH);
  128. return hr;
  129. }
  130. HRESULT CSaveAttachDlg::SaveAttachment(LPWSTR lpszDir, LPATTACHDATA pAttach)
  131. {
  132. HRESULT hr = S_OK;
  133. WCHAR wszRes[CCHMAX_STRINGRES],
  134. wsz[MAX_PATH + CCHMAX_STRINGRES],
  135. wszPath[MAX_PATH];
  136. int id;
  137. *wszRes = 0;
  138. Assert (pAttach);
  139. StrCpyNW(wszPath, lpszDir, ARRAYSIZE(wszPath));
  140. PathAppendW(wszPath, pAttach->szFileName);
  141. if (PathFileExistsW(wszPath))
  142. {
  143. LoadStringWrapW(g_hLocRes, idsFileExistWarning, wszRes, ARRAYSIZE(wszRes));
  144. wnsprintfW(wsz, ARRAYSIZE(wsz), wszRes, wszPath);
  145. // the file exists, warn the dude
  146. id = AthMessageBoxW(m_hwnd, MAKEINTRESOURCEW(idsSaveAttachments), wsz, NULL, MB_YESNOCANCEL|MB_DEFBUTTON2|MB_ICONEXCLAMATION);
  147. if (id == IDCANCEL)
  148. return MIMEEDIT_E_USERCANCEL;
  149. else
  150. if (id == IDNO)
  151. return S_OK;
  152. }
  153. return HrSaveAttachToFile(m_pMsg, pAttach->hAttach, wszPath);
  154. }
  155. HRESULT CSaveAttachDlg::OnInitDialog(HWND hwnd)
  156. {
  157. ULONG uAttach,
  158. cAttach;
  159. HBODY *rghAttach;
  160. LPATTACHDATA pAttach;
  161. LV_ITEMW lvi;
  162. LV_COLUMNW lvc;
  163. HIMAGELIST hImageList;
  164. RECT rc;
  165. m_hwnd = hwnd;
  166. CenterDialog(hwnd);
  167. // Set up edit box with passed in Directory
  168. m_hwndEdit = GetDlgItem(hwnd, idcPathEdit);
  169. if (!m_hwndEdit)
  170. return E_FAIL;
  171. if (m_rgchPath)
  172. SendMessageWrapW(m_hwndEdit, WM_SETTEXT, 0, (LPARAM)m_rgchPath);
  173. else
  174. {
  175. WCHAR szDir[MAX_PATH];
  176. HrGetLastOpenFileDirectoryW(ARRAYSIZE(szDir), szDir);
  177. SendMessageWrapW(m_hwndEdit, WM_SETTEXT, 0, LPARAM(szDir));
  178. }
  179. m_hwndList = GetDlgItem(hwnd, idcAttachList);
  180. AssertSz(m_hwndList, "Should have gotten an hwndList");
  181. ZeroMemory(&lvc, sizeof(lvc));
  182. lvc.mask = LVCF_TEXT | LVCF_WIDTH;
  183. lvc.cx = 0;
  184. ListView_InsertColumn(m_hwndList, 0, &lvc);
  185. ZeroMemory(&lvi, sizeof(lvi));
  186. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  187. Assert (m_pMsg);
  188. if (m_pMsg->GetAttachments(&cAttach, &rghAttach)==S_OK)
  189. {
  190. hImageList = ImageList_Create(GetSystemMetrics(SM_CXSMICON), GetSystemMetrics(SM_CYSMICON), FALSE, cAttach, 0);
  191. ListView_SetImageList(m_hwndList, hImageList, LVSIL_SMALL);
  192. for (uAttach=0; uAttach<cAttach; uAttach++)
  193. {
  194. if (HrAttachDataFromBodyPart(m_pMsg, rghAttach[uAttach], &pAttach)==S_OK)
  195. {
  196. if (!m_fShowUnsafe && pAttach && !pAttach->fSafe)
  197. continue;
  198. lvi.pszText = pAttach->szDisplay;
  199. lvi.iImage = ImageList_AddIcon(hImageList, pAttach->hIcon);
  200. lvi.lParam = (LPARAM)pAttach;
  201. if (SendMessage(m_hwndList, LVM_INSERTITEMW, 0, (LPARAM)(LV_ITEMW*)(&lvi)) == -1)
  202. {
  203. // try and keep crusing
  204. HrFreeAttachData(pAttach);
  205. pAttach=NULL;
  206. }
  207. }
  208. }
  209. SafeMemFree(rghAttach);
  210. }
  211. GetClientRect(m_hwndList, &rc);
  212. ListView_SetColumnWidth(m_hwndList, 0, rc.right);
  213. ListView_SetExtendedListViewStyle(m_hwndList, LVS_EX_FULLROWSELECT);
  214. ListView_SelectAll(m_hwndList);
  215. SetFocus(m_hwndList);
  216. return S_OK;
  217. }
  218. HRESULT CSaveAttachDlg::OnDestroy()
  219. {
  220. ULONG cItems;
  221. LV_ITEMW lvi;
  222. // walk the listview and free up the LPATTACHDATA hanging off each element
  223. if (m_hwndList &&
  224. (cItems = ListView_GetItemCount(m_hwndList)))
  225. {
  226. ZeroMemory(&lvi, sizeof(lvi));
  227. lvi.mask = LVIF_PARAM;
  228. for (lvi.iItem=0; lvi.iItem < (int)cItems; lvi.iItem++)
  229. {
  230. if (SendMessage(m_hwndList, LVM_GETITEMW, 0, (LPARAM)(LV_ITEMW*)(&lvi)))
  231. HrFreeAttachData((LPATTACHDATA)lvi.lParam);
  232. }
  233. }
  234. return S_OK;
  235. }
  236. HRESULT CSaveAttachDlg::OnWMNotfiy(WPARAM wParam, LPARAM lParam)
  237. {
  238. NM_LISTVIEW *pnmlv;
  239. LPNMHDR pnmh = NULL;
  240. UINT uiCode;
  241. if (idcAttachList == wParam)
  242. {
  243. pnmh = LPNMHDR(lParam);
  244. if (LVN_ITEMCHANGED == pnmh->code)
  245. {
  246. pnmlv = (NM_LISTVIEW *)pnmh;
  247. // Only do next section if changing selected states
  248. if ((!!(pnmlv->uOldState & LVIS_SELECTED) != (!!(pnmlv->uNewState & LVIS_SELECTED))))
  249. {
  250. // enable button is >0 items selected
  251. EnableWindow(GetDlgItem(m_hwnd, IDOK), ListView_GetSelectedCount(m_hwndList));
  252. }
  253. }
  254. }
  255. else if (idcPathEdit == wParam)
  256. {
  257. pnmh = LPNMHDR(lParam);
  258. if (NM_SETFOCUS == pnmh->code)
  259. SendMessage(m_hwndEdit, EM_SETSEL, 0, -1);
  260. }
  261. return S_FALSE;
  262. }
  263. INT_PTR CALLBACK CSaveAttachDlg::ExtDlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  264. {
  265. CSaveAttachDlg *pDlg = (CSaveAttachDlg *)GetWindowLongPtr(hwndDlg, DWLP_USER);
  266. if (uMsg == WM_INITDIALOG)
  267. {
  268. pDlg = (CSaveAttachDlg *)lParam;
  269. SetWindowLongPtr(hwndDlg, DWLP_USER, lParam);
  270. }
  271. return pDlg?pDlg->DlgProc(hwndDlg, uMsg, wParam, lParam):FALSE;
  272. }
  273. INT_PTR CSaveAttachDlg::DlgProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
  274. {
  275. switch (uMsg)
  276. {
  277. case WM_INITDIALOG:
  278. {
  279. if (SUCCEEDED(OnInitDialog(hwndDlg)))
  280. SHAutoComplete(m_hwndEdit, 0);
  281. return FALSE;
  282. }
  283. case WM_DESTROY:
  284. OnDestroy();
  285. break;
  286. case WM_NOTIFY:
  287. OnWMNotfiy(wParam, lParam);
  288. return 0;
  289. case WM_COMMAND:
  290. {
  291. switch (LOWORD(wParam))
  292. {
  293. case idcSelectAllAttBtn:
  294. ListView_SelectAll(m_hwndList);
  295. SetFocus(m_hwndList);
  296. return TRUE;
  297. case idcBrowseBtn:
  298. {
  299. WCHAR wszDir[MAX_PATH];
  300. HWND hwndEdit = GetDlgItem(hwndDlg, idcPathEdit);
  301. GetWindowTextWrapW(hwndEdit, wszDir, ARRAYSIZE(wszDir));
  302. if (BrowseForFolderW(g_hLocRes, hwndDlg, wszDir, MAX_PATH, idsPickAtachDir, FALSE))
  303. SetWindowTextWrapW(hwndEdit, wszDir);
  304. return TRUE;
  305. }
  306. case IDOK:
  307. if (SUCCEEDED(OnSave()))
  308. EndDialog(hwndDlg, S_OK);
  309. return TRUE;
  310. case IDCANCEL:
  311. EndDialog(hwndDlg, MIMEEDIT_E_USERCANCEL);
  312. return TRUE;
  313. }
  314. break;
  315. }
  316. }
  317. return FALSE;
  318. }
  319. HRESULT HrSaveAttachments(HWND hwnd, IMimeMessage *pMsg, LPWSTR lpszPath, ULONG cchPath, BOOL fShowUnsafe)
  320. {
  321. CSaveAttachDlg *pDlg;
  322. HRESULT hr;
  323. if (pMsg==NULL)
  324. return E_INVALIDARG;
  325. pDlg = new CSaveAttachDlg();
  326. if (!pDlg)
  327. return E_OUTOFMEMORY;
  328. hr = pDlg->Show(hwnd, pMsg, lpszPath, cchPath, fShowUnsafe);
  329. pDlg->Release();
  330. return hr;
  331. }