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.

1944 lines
58 KiB

  1. #include "pch.hxx"
  2. #include <shlwapi.h>
  3. #include <shlwapip.h>
  4. #include <resource.h>
  5. #include <options.h>
  6. #include <optres.h>
  7. #include <goptions.h>
  8. #include <strconst.h>
  9. #include <error.h>
  10. #include "sigs.h"
  11. #include "mimeolep.h"
  12. #include "demand.h"
  13. #include "menures.h"
  14. #include <mailnews.h>
  15. typedef struct tagSIG
  16. {
  17. IOptionBucket *pBckt;
  18. char szName[MAXSIGNAME];
  19. LPWSTR wszFile;
  20. LPSTR szText;
  21. DWORD type;
  22. BOOL fDelete;
  23. } SIG;
  24. typedef struct tagACCTSIG
  25. {
  26. IImnAccount *pAcct;
  27. ACCTTYPE type;
  28. int iSig;
  29. } ACCTSIG;
  30. typedef struct tagSIGOPT
  31. {
  32. SIG *pSig;
  33. int cSig;
  34. int cSigBuf;
  35. ACCTSIG *pAcctSig;
  36. int cAcctSig;
  37. int iDefSig;
  38. int iInvalidSig; // needed for commctrl
  39. BOOL fNoDirty;
  40. int iSelSig; // used by the advanced sig dialog
  41. } SIGOPT;
  42. HRESULT ValidateSig(HWND hwnd, HWND hwndList, int iSig, SIGOPT *pSigOpt);
  43. INT_PTR CALLBACK AdvSigDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
  44. void EnableSigOptions(HWND hwnd, BOOL fEnable);
  45. CSignatureManager *g_pSigMgr = NULL;
  46. const OPTIONINFO c_rgSigInfo[] =
  47. {
  48. {SIG_ID, VT_LPSTR, 0, NULL, NULL, 0, 0, MAXSIGID - 1, 0},
  49. {SIG_NAME, VT_LPSTR, 0, c_szSigName, NULL, 0, 0, MAXSIGNAME - 1, 0},
  50. {SIG_FILE, VT_LPWSTR, 0, c_szSigFile, NULL, 0, 0, MAX_PATH - 1, 0},
  51. {SIG_TEXT, VT_LPSTR, 0, c_szSigText, NULL, 0, 0, MAXSIGTEXT - 1, 0},
  52. {SIG_TYPE, VT_UI4, 0, c_szSigType, (LPCSTR)SIGTYPE_TEXT, 0, 0, 0, 0}
  53. };
  54. HRESULT InitSignatureManager(HKEY hkey, LPCSTR szRegRoot)
  55. {
  56. HRESULT hr;
  57. Assert(g_pSigMgr == NULL);
  58. Assert(g_pOpt != NULL);
  59. g_pSigMgr = new CSignatureManager(hkey, szRegRoot);
  60. if (g_pSigMgr == NULL)
  61. hr = E_OUTOFMEMORY;
  62. else
  63. hr = S_OK;
  64. return(hr);
  65. }
  66. HRESULT DeinitSignatureManager()
  67. {
  68. if (g_pSigMgr != NULL)
  69. {
  70. g_pSigMgr->Release();
  71. g_pSigMgr = NULL;
  72. }
  73. return(S_OK);
  74. }
  75. CSignatureManager::CSignatureManager(HKEY hkey, LPCSTR pszRegKeyRoot)
  76. {
  77. m_cRef = 1;
  78. m_fInit = FALSE;
  79. m_hkey = hkey;
  80. wnsprintf(m_szRegRoot, ARRAYSIZE(m_szRegRoot), c_szPathFileFmt, pszRegKeyRoot, c_szSigs);
  81. m_pBckt = NULL;
  82. m_cBckt = 0;
  83. m_cBcktBuf = 0;
  84. }
  85. CSignatureManager::~CSignatureManager(void)
  86. {
  87. int i;
  88. if (m_pBckt != NULL)
  89. {
  90. for (i = 0; i < m_cBckt; i++)
  91. {
  92. if (m_pBckt[i].pBckt != NULL)
  93. m_pBckt[i].pBckt->Release();
  94. }
  95. MemFree(m_pBckt);
  96. }
  97. }
  98. ULONG CSignatureManager::AddRef(void)
  99. {
  100. return((ULONG)InterlockedIncrement(&m_cRef));
  101. }
  102. ULONG CSignatureManager::Release(void)
  103. {
  104. LONG cRef = InterlockedDecrement(&m_cRef);
  105. if (0 == cRef)
  106. delete this;
  107. return((ULONG)cRef);
  108. }
  109. #define CSIGREALLOC 8
  110. HRESULT CSignatureManager::Initialize()
  111. {
  112. HKEY hkey;
  113. HRESULT hr;
  114. BOOL fDef;
  115. DWORD cSig, cSigBuf, cb, i;
  116. SIGBUCKET *pBckt;
  117. hr = S_OK;
  118. if (!m_fInit)
  119. {
  120. if (ERROR_SUCCESS == RegCreateKeyEx(m_hkey, m_szRegRoot, 0, NULL, REG_OPTION_NON_VOLATILE,
  121. KEY_READ, NULL, &hkey, &cb))
  122. {
  123. fDef = FALSE;
  124. cb = sizeof(m_szDefSigID);
  125. RegQueryValueEx(hkey, c_szRegDefSig, NULL, &i, (LPBYTE)m_szDefSigID, &cb);
  126. if (ERROR_SUCCESS == RegQueryInfoKey (hkey, NULL, NULL, NULL, &cSig, NULL,
  127. NULL, NULL, NULL, NULL, NULL, NULL))
  128. {
  129. cSigBuf = cSig + CSIGREALLOC;
  130. cb = cSigBuf * sizeof(SIGBUCKET);
  131. if (!MemAlloc((void **)&m_pBckt, cb))
  132. {
  133. hr = E_OUTOFMEMORY;
  134. }
  135. else
  136. {
  137. ZeroMemory(m_pBckt, cb);
  138. m_cBcktBuf = cSigBuf;
  139. for (i = 0, pBckt = m_pBckt; i < cSig; i++, pBckt++)
  140. {
  141. cb = sizeof(pBckt->szID);
  142. if (ERROR_SUCCESS != RegEnumKeyEx(hkey, i, pBckt->szID, &cb, NULL, NULL, NULL, NULL))
  143. {
  144. // TODO: what if this fails????
  145. break;
  146. }
  147. if (!fDef &&
  148. *m_szDefSigID != 0 &&
  149. 0 == lstrcmpi(m_szDefSigID, pBckt->szID))
  150. fDef = TRUE;
  151. m_cBckt++;
  152. }
  153. }
  154. }
  155. if (!fDef && m_cBckt > 0)
  156. {
  157. // there was no default or it was bogus, so just set it to the 1st sig
  158. StrCpyN(m_szDefSigID, m_pBckt->szID, ARRAYSIZE(m_szDefSigID));
  159. }
  160. RegCloseKey(hkey);
  161. }
  162. if (SUCCEEDED(hr))
  163. m_fInit = TRUE;
  164. }
  165. return(hr);
  166. }
  167. HRESULT CSignatureManager::GetBucket(SIGBUCKET *pSigBckt)
  168. {
  169. OPTBCKTINIT init;
  170. char szKey[MAX_PATH];
  171. IOptionBucketEx *pBcktEx;
  172. HRESULT hr;
  173. PROPVARIANT var;
  174. Assert(pSigBckt != NULL);
  175. Assert(pSigBckt->pBckt == NULL);
  176. hr = CreateOptionBucketEx(&pBcktEx);
  177. if (FAILED(hr))
  178. return(hr);
  179. ZeroMemory(&init, sizeof(OPTBCKTINIT));
  180. init.rgInfo = c_rgSigInfo;
  181. init.cInfo = ARRAYSIZE(c_rgSigInfo);
  182. init.hkey = m_hkey;
  183. wnsprintf(szKey, ARRAYSIZE(szKey), c_szPathFileFmt, m_szRegRoot, pSigBckt->szID);
  184. init.pszRegKeyBase = szKey;
  185. var.vt = VT_LPSTR;
  186. var.pszVal = pSigBckt->szID;
  187. if (FAILED(hr = pBcktEx->Initialize(&init)) ||
  188. FAILED(hr = pBcktEx->SetProperty(MAKEPROPSTRING(SIG_ID), &var, 0)))
  189. {
  190. pBcktEx->Release();
  191. return(hr);
  192. }
  193. hr = pBcktEx->QueryInterface(IID_IOptionBucket, (void **)&pSigBckt->pBckt);
  194. Assert(SUCCEEDED(hr));
  195. pBcktEx->Release();
  196. return(hr);
  197. }
  198. HRESULT CSignatureManager::GetSignature(LPCSTR szID, IOptionBucket **ppBckt)
  199. {
  200. HRESULT hr;
  201. SIGBUCKET *pBckt;
  202. int i;
  203. Assert(szID != NULL);
  204. Assert(ppBckt != NULL);
  205. AssertSz(m_cBckt, "Someone didn't check to see if we had any sigs");
  206. *ppBckt = NULL;
  207. hr = Initialize();
  208. if (SUCCEEDED(hr))
  209. {
  210. hr = E_FAIL;
  211. for (i = 0, pBckt = m_pBckt; i < m_cBckt; i++, pBckt++)
  212. {
  213. if (0 == lstrcmpi(pBckt->szID, szID))
  214. {
  215. hr = S_OK;
  216. if (pBckt->pBckt == NULL)
  217. hr = GetBucket(pBckt);
  218. if (SUCCEEDED(hr))
  219. {
  220. *ppBckt = pBckt->pBckt;
  221. (*ppBckt)->AddRef();
  222. }
  223. break;
  224. }
  225. }
  226. }
  227. return(hr);
  228. }
  229. HRESULT CSignatureManager::GetSignatureCount(int *pcSig)
  230. {
  231. HRESULT hr;
  232. Assert(pcSig != NULL);
  233. hr = Initialize();
  234. if (SUCCEEDED(hr))
  235. *pcSig = m_cBckt;
  236. return(hr);
  237. }
  238. HRESULT CSignatureManager::EnumSignatures(int index, IOptionBucket **ppBckt)
  239. {
  240. HRESULT hr;
  241. SIGBUCKET *pBckt;
  242. Assert(ppBckt != NULL);
  243. *ppBckt = NULL;
  244. hr = Initialize();
  245. if (SUCCEEDED(hr))
  246. {
  247. if (index >= m_cBckt)
  248. return(S_FALSE);
  249. hr = S_OK;
  250. pBckt = &m_pBckt[index];
  251. if (pBckt->pBckt == NULL)
  252. hr = GetBucket(pBckt);
  253. if (SUCCEEDED(hr))
  254. {
  255. *ppBckt = pBckt->pBckt;
  256. (*ppBckt)->AddRef();
  257. }
  258. }
  259. return(hr);
  260. }
  261. static const char c_szIDFmt[] = "%08lx";
  262. HRESULT CSignatureManager::CreateSignature(IOptionBucket **ppBckt)
  263. {
  264. HRESULT hr;
  265. int cAlloc;
  266. DWORD id, dwDisp;
  267. HKEY hkey;
  268. SIGBUCKET *pBckt;
  269. char szKey[MAX_PATH], szID[MAXSIGID];
  270. Assert(ppBckt != NULL);
  271. *ppBckt = NULL;
  272. hr = Initialize();
  273. if (SUCCEEDED(hr))
  274. {
  275. hr = E_FAIL;
  276. if (m_cBckt == m_cBcktBuf)
  277. {
  278. cAlloc = m_cBcktBuf + CSIGREALLOC;
  279. if (!MemRealloc((void **)&m_pBckt, cAlloc * sizeof(SIGBUCKET)))
  280. return(E_OUTOFMEMORY);
  281. m_cBcktBuf = cAlloc;
  282. ZeroMemory(&m_pBckt[m_cBckt], CSIGREALLOC * sizeof(SIGBUCKET));
  283. }
  284. pBckt = &m_pBckt[m_cBckt];
  285. id = 0;
  286. while (TRUE)
  287. {
  288. wnsprintf(szID, ARRAYSIZE(szID), c_szIDFmt, id);
  289. wnsprintf(szKey, ARRAYSIZE(szKey), c_szPathFileFmt, m_szRegRoot, szID);
  290. if (ERROR_SUCCESS == RegCreateKeyEx(m_hkey, szKey, 0, NULL, REG_OPTION_NON_VOLATILE,
  291. KEY_READ, NULL, &hkey, &dwDisp))
  292. {
  293. RegCloseKey(hkey);
  294. if (dwDisp == REG_OPENED_EXISTING_KEY)
  295. {
  296. id++;
  297. continue;
  298. }
  299. StrCpyN(pBckt->szID, szID, ARRAYSIZE(pBckt->szID));
  300. hr = GetBucket(pBckt);
  301. if (SUCCEEDED(hr))
  302. {
  303. m_cBckt++;
  304. *ppBckt = pBckt->pBckt;
  305. (*ppBckt)->AddRef();
  306. }
  307. else
  308. {
  309. RegDeleteKey(m_hkey, szKey);
  310. }
  311. }
  312. break;
  313. }
  314. }
  315. return(hr);
  316. }
  317. HRESULT CSignatureManager::DeleteSignature(LPCSTR szID)
  318. {
  319. HRESULT hr;
  320. char sz[MAX_PATH],
  321. szSigID[MAXSIGID];
  322. int i;
  323. SIGBUCKET *pBckt;
  324. ACCTTYPE type;
  325. IImnAccount *pAcct;
  326. IImnEnumAccounts *pEnum;
  327. BOOL fDeletingDefault = FALSE;
  328. hr = Initialize();
  329. if (SUCCEEDED(hr))
  330. {
  331. hr = E_FAIL;
  332. for (i = 0, pBckt = m_pBckt; i < m_cBckt; i++, pBckt++)
  333. {
  334. if (0 == lstrcmpi(pBckt->szID, szID))
  335. {
  336. fDeletingDefault = (0 == lstrcmpi(pBckt->szID, m_szDefSigID));
  337. wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, m_szRegRoot, szID);
  338. if (ERROR_SUCCESS == SHDeleteKey(m_hkey, sz))
  339. {
  340. if (pBckt->pBckt != NULL)
  341. {
  342. pBckt->pBckt->Release();
  343. pBckt->pBckt = NULL;
  344. }
  345. if (i + 1 < m_cBckt)
  346. MoveMemory(&m_pBckt[i], &m_pBckt[i + 1], (m_cBckt - (i + 1)) * sizeof(SIGBUCKET));
  347. m_cBckt--;
  348. m_pBckt[m_cBckt].pBckt = NULL;
  349. hr = S_OK;
  350. Assert(g_pAcctMan != NULL);
  351. if (SUCCEEDED(g_pAcctMan->Enumerate(SRV_MAIL | SRV_NNTP, &pEnum)))
  352. {
  353. Assert(pEnum != NULL);
  354. while (SUCCEEDED(pEnum->GetNext(&pAcct)))
  355. {
  356. Assert(pAcct != NULL);
  357. hr = pAcct->GetAccountType(&type);
  358. Assert(SUCCEEDED(hr));
  359. if (SUCCEEDED(pAcct->GetPropSz(type == ACCT_MAIL ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE, szSigID, ARRAYSIZE(szSigID))) &&
  360. 0 == lstrcmpi(szSigID, szID))
  361. {
  362. pAcct->SetPropSz(type == ACCT_MAIL ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE, NULL);
  363. pAcct->SaveChanges();
  364. }
  365. pAcct->Release();
  366. }
  367. pEnum->Release();
  368. }
  369. }
  370. break;
  371. }
  372. }
  373. if (fDeletingDefault)
  374. {
  375. if (m_cBckt > 0)
  376. SetDefaultSignature(m_pBckt->szID);
  377. else
  378. SetDefaultSignature("");
  379. }
  380. }
  381. return(hr);
  382. }
  383. HRESULT CSignatureManager::GetDefaultSignature(LPSTR pszID, DWORD cchSize)
  384. {
  385. HRESULT hr;
  386. AssertSz(m_cBckt, "Someone didn't check to see if we had any sigs");
  387. hr = Initialize();
  388. if (SUCCEEDED(hr))
  389. StrCpyN(pszID, m_szDefSigID, cchSize);
  390. return(hr);
  391. }
  392. HRESULT CSignatureManager::SetDefaultSignature(LPCSTR szID)
  393. {
  394. HRESULT hr;
  395. Assert(szID != NULL);
  396. Assert(lstrlen(szID) < MAXSIGID);
  397. hr = Initialize();
  398. if (SUCCEEDED(hr))
  399. {
  400. if (ERROR_SUCCESS == SHSetValue(m_hkey, m_szRegRoot, c_szRegDefSig, REG_SZ, szID, lstrlen(szID) + 1))
  401. StrCpyN(m_szDefSigID, szID, ARRAYSIZE(m_szDefSigID));
  402. else
  403. hr = E_FAIL;
  404. }
  405. return(hr);
  406. }
  407. // TODO: error handling would be useful
  408. SIGOPT *InitSigOpt(void)
  409. {
  410. HRESULT hr;
  411. int i, cSig;
  412. SIG *pSig;
  413. char szDef[MAXSIGID];
  414. PROPVARIANT var;
  415. SIGOPT *pSigOpt = NULL;
  416. Assert(g_pSigMgr != NULL);
  417. if (MemAlloc((void **)&pSigOpt, sizeof(SIGOPT)))
  418. {
  419. ZeroMemory(pSigOpt, sizeof(SIGOPT));
  420. pSigOpt->iDefSig = -1;
  421. pSigOpt->iInvalidSig = -1;
  422. hr = g_pSigMgr->GetSignatureCount(&cSig);
  423. Assert(SUCCEEDED(hr));
  424. if (cSig > 0)
  425. {
  426. pSigOpt->cSigBuf = cSig + CSIGREALLOC;
  427. if (MemAlloc((void **)&pSigOpt->pSig, pSigOpt->cSigBuf * sizeof(SIG)))
  428. {
  429. ZeroMemory(pSigOpt->pSig, pSigOpt->cSigBuf * sizeof(SIG));
  430. hr = g_pSigMgr->GetDefaultSignature(szDef, ARRAYSIZE(szDef));
  431. Assert(SUCCEEDED(hr));
  432. Assert(szDef[0] != 0);
  433. for (i = 0, pSig = pSigOpt->pSig; i < cSig; i++, pSig++)
  434. {
  435. hr = g_pSigMgr->EnumSignatures(i, &pSig->pBckt);
  436. if (hr != S_OK)
  437. break;
  438. Assert(pSig->pBckt != NULL);
  439. if (pSigOpt->iDefSig == -1)
  440. {
  441. hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0);
  442. Assert(SUCCEEDED(hr));
  443. Assert(var.vt == VT_LPSTR);
  444. Assert(var.pszVal != NULL);
  445. if (0 == lstrcmpi(szDef, var.pszVal))
  446. pSigOpt->iDefSig = i;
  447. MemFree(var.pszVal);
  448. }
  449. hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_NAME), &var, 0);
  450. Assert(SUCCEEDED(hr));
  451. Assert(var.vt == VT_LPSTR);
  452. Assert(var.pszVal != NULL);
  453. StrCpyN(pSig->szName, var.pszVal, ARRAYSIZE(pSig->szName));
  454. MemFree(var.pszVal);
  455. hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_TYPE), &var, 0);
  456. Assert(SUCCEEDED(hr));
  457. Assert(var.vt == VT_UI4);
  458. pSig->type = var.ulVal;
  459. if (pSig->type == SIGTYPE_TEXT)
  460. {
  461. hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_TEXT), &var, 0);
  462. Assert(SUCCEEDED(hr));
  463. Assert(var.vt == VT_LPSTR);
  464. Assert(var.pszVal != NULL);
  465. pSig->szText = var.pszVal;
  466. }
  467. else
  468. {
  469. Assert(pSig->type == SIGTYPE_FILE);
  470. hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_FILE), &var, 0);
  471. Assert(SUCCEEDED(hr));
  472. Assert(var.vt == VT_LPWSTR);
  473. Assert(var.pwszVal != NULL);
  474. pSig->wszFile = var.pwszVal;
  475. }
  476. pSigOpt->cSig++;
  477. }
  478. }
  479. }
  480. }
  481. return(pSigOpt);
  482. }
  483. void DeinitSigOpt(SIGOPT *pSigOpt)
  484. {
  485. int i;
  486. SIG *pSig;
  487. ACCTSIG *pAcctSig;
  488. if (pSigOpt != NULL)
  489. {
  490. if (pSigOpt->pSig != NULL)
  491. {
  492. for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++)
  493. {
  494. if (pSig->wszFile != NULL)
  495. MemFree(pSig->wszFile);
  496. if (pSig->szText != NULL)
  497. MemFree(pSig->szText);
  498. if (pSig->pBckt != NULL)
  499. pSig->pBckt->Release();
  500. }
  501. MemFree(pSigOpt->pSig);
  502. }
  503. if (pSigOpt->pAcctSig != NULL)
  504. {
  505. for (i = 0, pAcctSig = pSigOpt->pAcctSig; i < pSigOpt->cAcctSig; i++, pAcctSig++)
  506. {
  507. if (pAcctSig->pAcct != NULL)
  508. pAcctSig->pAcct->Release();
  509. }
  510. MemFree(pSigOpt->pAcctSig);
  511. }
  512. MemFree(pSigOpt);
  513. }
  514. }
  515. int InsertSig(HWND hwndList, SIG *pSig, int i)
  516. {
  517. int index;
  518. LV_ITEM lvi;
  519. Assert(pSig != NULL);
  520. lvi.mask = LVIF_TEXT | LVIF_PARAM;
  521. lvi.iItem = i;
  522. lvi.iSubItem = 0;
  523. lvi.pszText = pSig->szName;
  524. lvi.lParam = i;
  525. index = ListView_InsertItem(hwndList, &lvi);
  526. Assert(index != -1);
  527. return(index);
  528. }
  529. void SetDefault(HWND hwndList, int iOldDef, int iNewDef)
  530. {
  531. char sz[64];
  532. LV_FINDINFO lvfi;
  533. int i;
  534. if (iOldDef >= 0)
  535. {
  536. lvfi.flags = LVFI_PARAM;
  537. lvfi.lParam = iOldDef;
  538. i = ListView_FindItem(hwndList, -1, &lvfi);
  539. ListView_SetItemText(hwndList, i, 1, (LPSTR)c_szEmpty);
  540. }
  541. lvfi.flags = LVFI_PARAM;
  542. lvfi.lParam = iNewDef;
  543. i = ListView_FindItem(hwndList, -1, &lvfi);
  544. AthLoadString(idsDefaultSignature, sz, ARRAYSIZE(sz));
  545. ListView_SetItemText(hwndList, i, 1, sz);
  546. }
  547. void EnableSignatureWindows(HWND hwnd, BOOL fEnable)
  548. {
  549. EnableWindow(GetDlgItem(hwnd, IDC_REMOVE_BUTTON), fEnable);
  550. EnableWindow(GetDlgItem(hwnd, IDC_RENAME_BUTTON), fEnable);
  551. EnableWindow(GetDlgItem(hwnd, IDC_TEXT_RADIO), fEnable);
  552. EnableWindow(GetDlgItem(hwnd, IDC_TEXT_EDIT), fEnable);
  553. EnableWindow(GetDlgItem(hwnd, IDC_FILE_RADIO), fEnable);
  554. EnableWindow(GetDlgItem(hwnd, IDC_FILE_EDIT), fEnable);
  555. EnableWindow(GetDlgItem(hwnd, IDC_BROWSE_BUTTON), fEnable);
  556. EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), fEnable);
  557. EnableWindow(GetDlgItem(hwnd, IDC_ADV_BUTTON), fEnable);
  558. if (!fEnable)
  559. {
  560. CheckDlgButton(hwnd, IDC_TEXT_RADIO, BST_UNCHECKED);
  561. SetDlgItemText(hwnd, IDC_TEXT_EDIT, c_szEmpty);
  562. CheckDlgButton(hwnd, IDC_FILE_RADIO, BST_UNCHECKED);
  563. SetDlgItemText(hwnd, IDC_FILE_EDIT, c_szEmpty);
  564. if (!IsWindowEnabled(GetFocus()))
  565. SetFocus(GetDlgItem(hwnd, IDC_NEW_BUTTON));
  566. }
  567. }
  568. WNDPROC g_SigListUnicodeProc = NULL;
  569. LRESULT CALLBACK SigListANSIProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  570. {
  571. return(CallWindowProc(g_SigListUnicodeProc, hwnd, msg, wParam, lParam));
  572. }
  573. void InitSigDlg(HWND hwnd, SIGOPT *pSigOpt, OPTINFO *poi)
  574. {
  575. HWND hwndList, hwndT;
  576. RECT rc;
  577. int i;
  578. DWORD dw;
  579. LV_COLUMN lvc;
  580. SIG *pSig;
  581. Assert(pSigOpt != NULL);
  582. hwndT = GetDlgItem(hwnd, IDC_TEXT_EDIT);
  583. SetIntlFont(hwndT);
  584. SendMessage(hwndT, EM_LIMITTEXT, MAXSIGTEXT - 1, 0);
  585. hwndT = GetDlgItem(hwnd, IDC_FILE_EDIT);
  586. SetIntlFont(hwndT);
  587. SendMessage(hwndT, EM_LIMITTEXT, MAX_PATH - 1, 0);
  588. dw = IDwGetOption(poi->pOpt, OPT_SIGNATURE_FLAGS);
  589. CheckDlgButton(hwnd, IDC_ADDSIG_CHECK,
  590. !!(dw & SIGFLAG_AUTONEW) ? BST_CHECKED : BST_UNCHECKED);
  591. CheckDlgButton(hwnd, IDC_ADDREPLY_CHECK,
  592. !(dw & SIGFLAG_AUTOREPLY) ? BST_CHECKED : BST_UNCHECKED);
  593. if (!(dw & SIGFLAG_AUTONEW))
  594. EnableWindow(GetDlgItem(hwnd, IDC_ADDREPLY_CHECK), FALSE);
  595. hwndList = GetDlgItem(hwnd, IDC_SIG_LIST);
  596. g_SigListUnicodeProc = (WNDPROC) SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR)SigListANSIProc);
  597. GetClientRect(hwndList, &rc);
  598. rc.right = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  599. rc.right = rc.right / 2;
  600. lvc.mask = LVCF_WIDTH;
  601. lvc.cx = rc.right;
  602. ListView_InsertColumn(hwndList, 0, &lvc);
  603. ListView_InsertColumn(hwndList, 1, &lvc);
  604. for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++)
  605. InsertSig(hwndList, pSig, i);
  606. if (pSigOpt->iDefSig >= 0)
  607. SetDefault(hwndList, -1, pSigOpt->iDefSig);
  608. if (pSigOpt->cSig > 0)
  609. {
  610. ListView_SetItemState(hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  611. }
  612. else
  613. {
  614. EnableSignatureWindows(hwnd, FALSE);
  615. EnableSigOptions(hwnd, FALSE);
  616. }
  617. // Pictures
  618. HICON hIcon;
  619. hIcon = ImageList_GetIcon(poi->himl, ID_SIGNATURES, ILD_TRANSPARENT);
  620. SendDlgItemMessage(hwnd, IDC_SIG_SETTINGS_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
  621. hIcon = ImageList_GetIcon(poi->himl, ID_SIG_LIST, ILD_TRANSPARENT);
  622. SendDlgItemMessage(hwnd, IDC_SIGLIST_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
  623. hIcon = ImageList_GetIcon(poi->himl, ID_SIG_EDIT, ILD_TRANSPARENT);
  624. SendDlgItemMessage(hwnd, IDC_SIG_EDIT_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon);
  625. }
  626. BOOL IsUniqueSigName(LPCSTR szName, SIGOPT *pSigOpt)
  627. {
  628. int i;
  629. SIG *pSig;
  630. for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++)
  631. {
  632. if (!pSig->fDelete &&
  633. 0 == lstrcmpi(szName, pSig->szName))
  634. return(FALSE);
  635. }
  636. return(TRUE);
  637. }
  638. int GetItemIndex(HWND hwndList, int i)
  639. {
  640. LV_ITEM lvi;
  641. if (i == -1)
  642. {
  643. // get the selected item's index
  644. i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED);
  645. Assert(i >= 0);
  646. }
  647. lvi.iItem = i;
  648. lvi.iSubItem = 0;
  649. lvi.mask = LVIF_PARAM;
  650. ListView_GetItem(hwndList, &lvi);
  651. return((int)(INT_PTR)(lvi.lParam));
  652. }
  653. HRESULT HandleNewSig(HWND hwnd, SIGOPT *pSigOpt)
  654. {
  655. HRESULT hr;
  656. SIG *pSig;
  657. char sz[MAXSIGNAME];
  658. int i, cSig, cAlloc;
  659. HWND hwndList;
  660. hwndList = GetDlgItem(hwnd, IDC_SIG_LIST);
  661. cSig = ListView_GetItemCount(hwndList);
  662. if (cSig > 0)
  663. {
  664. i = GetItemIndex(hwndList, -1);
  665. if (i >= 0)
  666. {
  667. hr = ValidateSig(hwnd, hwndList, i, pSigOpt);
  668. if (FAILED(hr))
  669. return(E_FAIL);
  670. }
  671. }
  672. if (pSigOpt->cSig == pSigOpt->cSigBuf)
  673. {
  674. cAlloc = pSigOpt->cSigBuf + CSIGREALLOC;
  675. if (!MemRealloc((void **)&pSigOpt->pSig, cAlloc * sizeof(SIG)))
  676. return(E_OUTOFMEMORY);
  677. ZeroMemory(&pSigOpt->pSig[pSigOpt->cSig], CSIGREALLOC * sizeof(SIG));
  678. pSigOpt->cSigBuf = cAlloc;
  679. }
  680. pSig = &pSigOpt->pSig[pSigOpt->cSig];
  681. AthLoadString(idsSigNameFmt, sz, ARRAYSIZE(sz));
  682. for (i = 1; i < 10000; i++)
  683. {
  684. wnsprintf(pSig->szName, ARRAYSIZE(pSig->szName), sz, i);
  685. if (IsUniqueSigName(pSig->szName, pSigOpt))
  686. break;
  687. }
  688. if (i == 10000)
  689. return(E_FAIL);
  690. pSig->type = SIGTYPE_TEXT;
  691. i = InsertSig(hwndList, pSig, pSigOpt->cSig);
  692. if (pSigOpt->iDefSig == -1)
  693. {
  694. SetDefault(hwndList, -1, pSigOpt->cSig);
  695. pSigOpt->iDefSig = pSigOpt->cSig;
  696. }
  697. pSigOpt->cSig++;
  698. if (cSig == 0)
  699. {
  700. EnableSignatureWindows(hwnd, TRUE);
  701. EnableSigOptions(hwnd, TRUE);
  702. }
  703. EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), pSigOpt->iDefSig != GetItemIndex(hwndList, i));
  704. ListView_SetItemState(hwndList, i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  705. ListView_EnsureVisible(hwndList, i, FALSE);
  706. SetFocus(GetDlgItem(hwnd, IDC_TEXT_EDIT));
  707. return(S_OK);
  708. }
  709. HRESULT HandleDeleteSig(HWND hwnd, SIGOPT *pSigOpt)
  710. {
  711. int i, iSig, iNewSel, cSig;
  712. HWND hwndList;
  713. SIG *pSig;
  714. hwndList = GetDlgItem(hwnd, IDC_SIG_LIST);
  715. i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED);
  716. Assert(i >= 0);
  717. iSig = GetItemIndex(hwndList, i);
  718. pSig = &pSigOpt->pSig[iSig];
  719. Assert(!pSig->fDelete);
  720. pSig->fDelete = TRUE;
  721. ListView_DeleteItem(hwndList, i);
  722. cSig = ListView_GetItemCount(hwndList);
  723. if (cSig == 0)
  724. iNewSel = -1;
  725. else if (i == 0)
  726. iNewSel = 0;
  727. else
  728. iNewSel = i - 1;
  729. Assert(pSigOpt->iDefSig >= 0);
  730. if (iSig == pSigOpt->iDefSig)
  731. {
  732. if (iNewSel >= 0)
  733. {
  734. iSig = GetItemIndex(hwndList, iNewSel);
  735. SetDefault(hwndList, -1, iSig);
  736. pSigOpt->iDefSig = iSig;
  737. EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), FALSE);
  738. }
  739. else
  740. {
  741. pSigOpt->iDefSig = -1;
  742. }
  743. }
  744. if (iNewSel >= 0)
  745. {
  746. ListView_SetItemState(hwndList, iNewSel, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  747. ListView_EnsureVisible(hwndList, iNewSel, FALSE);
  748. }
  749. else
  750. {
  751. EnableSignatureWindows(hwnd, FALSE);
  752. EnableSigOptions(hwnd, FALSE);
  753. }
  754. return(S_OK);
  755. }
  756. HRESULT HandleSigRename(HWND hwnd, LV_DISPINFO *pdi, SIGOPT *pSigOpt)
  757. {
  758. HWND hwndList;
  759. SIG *pSig, *pSigT;
  760. LPSTR pszText = NULL;
  761. HRESULT hr = S_OK;
  762. int i;
  763. Assert(pdi != NULL);
  764. Assert(pSigOpt != NULL);
  765. IF_TRUEEXIT((pdi->item.pszText == NULL || FIsEmpty(pdi->item.pszText)), S_FALSE);
  766. if(IsWindowUnicode(hwnd))
  767. pszText = PszToANSI(CP_ACP, (WCHAR*)(pdi->item.pszText));
  768. else
  769. pszText = StrDupA(pdi->item.pszText);
  770. IF_NULLEXIT(pszText);
  771. IF_TRUEEXIT((lstrlen(pszText) >= MAXSIGNAME), S_FALSE);
  772. pSig = &pSigOpt->pSig[pdi->item.lParam];
  773. Assert(!pSig->fDelete);
  774. Assert(pSig->szName[0] != 0);
  775. IF_TRUEEXIT((0 == lstrcmpi(pSig->szName, pszText)), S_FALSE);
  776. for (i = 0, pSigT = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSigT++)
  777. {
  778. if (pSigT->fDelete)
  779. continue;
  780. IF_TRUEEXIT((0 == lstrcmpi(pSigT->szName, pszText)), S_FALSE);
  781. }
  782. StrCpyN(pSig->szName, pszText, ARRAYSIZE(pSig->szName));
  783. exit:
  784. MemFree(pszText);
  785. return hr;
  786. }
  787. static const int c_rgidsFilter[] =
  788. {
  789. idsTextFileFilter,
  790. idsHtmlFileFilter,
  791. idsAllFilesFilter
  792. };
  793. HRESULT HandleBrowseButton(HWND hwnd)
  794. {
  795. OPENFILENAMEW ofnw;
  796. WCHAR wszFilter[MAX_PATH], wszFile[MAX_PATH], wszDir[MAX_PATH];
  797. HRESULT hr;
  798. int cch;
  799. LPWSTR pwszFile;
  800. hr = S_FALSE;
  801. *wszFilter = 0;
  802. *wszFile = 0;
  803. ZeroMemory(&ofnw, sizeof(ofnw));
  804. ofnw.lStructSize = sizeof(ofnw);
  805. cch = GetDlgItemTextWrapW(hwnd, IDC_FILE_EDIT, wszDir, ARRAYSIZE(wszDir));
  806. if (cch > 0)
  807. {
  808. if (PathIsDirectoryW(wszDir))
  809. {
  810. ofnw.lpstrInitialDir = wszDir;
  811. }
  812. else if (PathFileExistsW(wszDir))
  813. {
  814. pwszFile = PathFindFileNameW(wszDir);
  815. if (pwszFile != NULL)
  816. StrCpyNW(wszFile, pwszFile, ARRAYSIZE(wszFile));
  817. *pwszFile = 0;
  818. if (*wszDir != 0)
  819. ofnw.lpstrInitialDir = wszDir;
  820. }
  821. else if (PathIsFileSpecW(wszDir))
  822. {
  823. StrCpyNW(wszFile, wszDir, ARRAYSIZE(wszFile));
  824. }
  825. }
  826. CombineFiltersW((int *)c_rgidsFilter, ARRAYSIZE(c_rgidsFilter), wszFilter);
  827. ofnw.hwndOwner = hwnd;
  828. ofnw.lpstrFile = wszFile;
  829. ofnw.lpstrFilter = wszFilter;
  830. ofnw.nMaxFile = ARRAYSIZE(wszFile);
  831. ofnw.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NONETWORKBUTTON | OFN_NOCHANGEDIR | OFN_EXPLORER;
  832. if (HrAthGetFileNameW(&ofnw, TRUE)==S_OK)
  833. {
  834. SetDlgItemTextWrapW(hwnd, IDC_FILE_EDIT, wszFile);
  835. hr = S_OK;
  836. }
  837. return(hr);
  838. }
  839. HRESULT ValidateSig(HWND hwnd, HWND hwndList, int iSig, SIGOPT *pSigOpt)
  840. {
  841. SIG *pSig;
  842. BOOL fText;
  843. HWND hwndT;
  844. int cch, id, i;
  845. char **ppsz, *psz;
  846. Assert(pSigOpt != NULL);
  847. Assert(iSig < pSigOpt->cSig);
  848. pSig = &pSigOpt->pSig[iSig];
  849. if (pSig->fDelete)
  850. return(S_OK);
  851. fText = (IsDlgButtonChecked(hwnd, IDC_TEXT_RADIO) == BST_CHECKED);
  852. id = fText ? IDC_TEXT_EDIT : IDC_FILE_EDIT;
  853. hwndT = GetDlgItem(hwnd, id);
  854. cch = GetWindowTextLength(hwndT);
  855. if (cch == 0)
  856. {
  857. i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED);
  858. ListView_SetItemState(hwndList, i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  859. InvalidOptionProp(hwnd, id, fText ? idsEnterSigText : idsEnterSigFile, iddOpt_Signature);
  860. return(E_FAIL);
  861. }
  862. cch++;
  863. if (!fText)
  864. {
  865. WCHAR *pwsz = NULL;
  866. if (!MemAlloc((void **)&pwsz, cch * sizeof(*pwsz)))
  867. return(E_OUTOFMEMORY);
  868. GetWindowTextWrapW(hwndT, pwsz, cch);
  869. if (!PathFileExistsW(pwsz) || PathIsDirectoryW(pwsz))
  870. {
  871. MemFree(pwsz);
  872. i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED);
  873. ListView_SetItemState(hwndList, i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  874. InvalidOptionProp(hwnd, id, idsSigFileNoExistError, iddOpt_Signature);
  875. return(E_FAIL);
  876. }
  877. else
  878. {
  879. //Free the previous sig file
  880. MemFree(pSig->wszFile);
  881. pSig->wszFile = pwsz;
  882. }
  883. }
  884. else
  885. {
  886. if (!MemAlloc((void **)&psz, cch))
  887. return(E_OUTOFMEMORY);
  888. GetWindowText(hwndT, psz, cch);
  889. //Free the previous sig text
  890. MemFree(pSig->szText);
  891. pSig->szText = psz;
  892. }
  893. pSig->type = fText ? SIGTYPE_TEXT : SIGTYPE_FILE;
  894. return(S_OK);
  895. }
  896. HRESULT SaveSigs(HWND hwnd, SIGOPT *pSigOpt)
  897. {
  898. int cSigT, cSig, i;
  899. SIG *pSig;
  900. ACCTSIG *pAcctSig;
  901. PROPVARIANT var;
  902. HRESULT hr;
  903. HWND hwndList;
  904. char *szSigID;
  905. Assert(pSigOpt != NULL);
  906. Assert(g_pSigMgr != NULL);
  907. hwndList = GetDlgItem(hwnd, IDC_SIG_LIST);
  908. cSig = ListView_GetItemCount(hwndList);
  909. cSigT = 0;
  910. for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++)
  911. {
  912. if (pSig->fDelete)
  913. {
  914. if (pSig->pBckt != NULL)
  915. {
  916. if (SUCCEEDED(pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0)) && var.pszVal != NULL)
  917. {
  918. g_pSigMgr->DeleteSignature(var.pszVal);
  919. MemFree(var.pszVal);
  920. }
  921. }
  922. continue;
  923. }
  924. else
  925. {
  926. if (pSig->pBckt == NULL)
  927. {
  928. hr = g_pSigMgr->CreateSignature(&pSig->pBckt);
  929. Assert(SUCCEEDED(hr));
  930. Assert(pSig->pBckt != NULL);
  931. }
  932. if (pSigOpt->iDefSig == i)
  933. {
  934. if (SUCCEEDED(pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0)) && var.pszVal)
  935. {
  936. g_pSigMgr->SetDefaultSignature(var.pszVal);
  937. MemFree(var.pszVal);
  938. }
  939. }
  940. var.vt = VT_LPSTR;
  941. var.pszVal = pSig->szName;
  942. hr = pSig->pBckt->SetProperty(MAKEPROPSTRING(SIG_NAME), &var, 0);
  943. AssertSz(SUCCEEDED(hr), "Sig name failed to be set");
  944. var.vt = VT_UI4;
  945. var.ulVal = pSig->type;
  946. hr = pSig->pBckt->SetProperty(MAKEPROPSTRING(SIG_TYPE), &var, 0);
  947. AssertSz(SUCCEEDED(hr), "Sig type failed to be set");
  948. var.vt = VT_LPSTR;
  949. AssertSz(((SIGTYPE_TEXT == pSig->type) ? (NULL != pSig->szText) : TRUE), "Text should be set.");
  950. var.pszVal = (SIGTYPE_TEXT == pSig->type) ? pSig->szText : (LPSTR)c_szEmpty;
  951. hr = pSig->pBckt->SetProperty(MAKEPROPSTRING(SIG_TEXT), &var, 0);
  952. AssertSz(SUCCEEDED(hr), "Sig text failed to be set");
  953. var.vt = VT_LPWSTR;
  954. var.pwszVal = (pSig->type == SIGTYPE_FILE) ? pSig->wszFile : (LPWSTR)c_wszEmpty;
  955. hr = pSig->pBckt->SetProperty(MAKEPROPSTRING(SIG_FILE), &var, 0);
  956. AssertSz(SUCCEEDED(hr), "Sig filename failed to be set");
  957. cSigT++;
  958. }
  959. }
  960. Assert(cSig == cSigT);
  961. for (i = 0, pAcctSig = pSigOpt->pAcctSig; i < pSigOpt->cAcctSig; i++, pAcctSig++)
  962. {
  963. szSigID = NULL;
  964. if (pAcctSig->iSig >= 0)
  965. {
  966. pSig = &pSigOpt->pSig[pAcctSig->iSig];
  967. if (!pSig->fDelete)
  968. {
  969. hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0);
  970. Assert(SUCCEEDED(hr));
  971. Assert(var.pszVal != NULL);
  972. szSigID = var.pszVal;
  973. }
  974. }
  975. hr = pAcctSig->pAcct->SetPropSz(pAcctSig->type == ACCT_MAIL ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE, szSigID);
  976. Assert(SUCCEEDED(hr));
  977. hr = pAcctSig->pAcct->SaveChanges();
  978. Assert(SUCCEEDED(hr));
  979. if (szSigID != NULL)
  980. MemFree(szSigID);
  981. }
  982. return(S_OK);
  983. }
  984. void EnableSigWindows(HWND hwnd, BOOL fText)
  985. {
  986. HWND focus;
  987. focus = GetFocus();
  988. EnableWindow(GetDlgItem(hwnd, IDC_TEXT_EDIT), fText);
  989. EnableWindow(GetDlgItem(hwnd, IDC_FILE_EDIT), !fText);
  990. EnableWindow(GetDlgItem(hwnd, IDC_BROWSE_BUTTON), !fText);
  991. // don't disable button that has the focus
  992. if (!IsWindowEnabled(focus))
  993. SetFocus(GetDlgItem(hwnd, fText ? IDC_TEXT_EDIT : IDC_FILE_EDIT));
  994. }
  995. void EnableSigOptions(HWND hwnd, BOOL fEnable)
  996. {
  997. HWND hwndT;
  998. hwndT = GetDlgItem(hwnd, IDC_ADDSIG_CHECK);
  999. EnableWindow(hwndT, fEnable);
  1000. if (fEnable)
  1001. fEnable = (SendMessage(hwndT, BM_GETCHECK, 0, 0) == BST_CHECKED);
  1002. EnableWindow(GetDlgItem(hwnd, IDC_ADDREPLY_CHECK), fEnable);
  1003. }
  1004. static const HELPMAP g_rgCtxMapSigs[] = {
  1005. {IDC_ADDSIG_CHECK, 353569},
  1006. {IDC_ADDREPLY_CHECK, 35610},
  1007. {IDC_SIG_LIST, 35594},
  1008. {IDC_NEW_BUTTON, 35591},
  1009. {IDC_REMOVE_BUTTON, 35592},
  1010. {IDC_RENAME_BUTTON, 35593},
  1011. {IDC_TEXT_EDIT, 35595},
  1012. {IDC_FILE_EDIT, 35600},
  1013. {IDC_DEFAULT_BUTTON, 35596},
  1014. {IDC_ADV_BUTTON, 35597},
  1015. {IDC_BROWSE_BUTTON, 35605},
  1016. {idcStatic1, IDH_NEWS_COMM_GROUPBOX},
  1017. {idcStatic2, IDH_NEWS_COMM_GROUPBOX},
  1018. {idcStatic3, IDH_NEWS_COMM_GROUPBOX},
  1019. {idcStatic4, IDH_NEWS_COMM_GROUPBOX},
  1020. {idcStatic5, IDH_NEWS_COMM_GROUPBOX},
  1021. {idcStatic6, IDH_NEWS_COMM_GROUPBOX},
  1022. {IDC_SIG_SETTINGS_ICON, IDH_NEWS_COMM_GROUPBOX},
  1023. {IDC_SIGLIST_ICON, IDH_NEWS_COMM_GROUPBOX},
  1024. {IDC_SIG_EDIT_ICON, IDH_NEWS_COMM_GROUPBOX},
  1025. {0, 0}
  1026. };
  1027. WNDPROC g_SigRenameEditUnicodeProc = NULL;
  1028. LRESULT CALLBACK SigRenameEditANSIProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1029. {
  1030. return(CallWindowProc(g_SigRenameEditUnicodeProc, hwnd, msg, wParam, lParam));
  1031. }
  1032. INT_PTR CALLBACK SigDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1033. {
  1034. SIGOPT *pSigOpt;
  1035. WORD code, id;
  1036. SIG *pSig;
  1037. int i, cSig;
  1038. DWORD dw;
  1039. OPTINFO *poi;
  1040. LPNMHDR pnmh;
  1041. NM_LISTVIEW *pnmlv;
  1042. HRESULT hr;
  1043. HWND hwndList;
  1044. BOOL fEnable, fRet = TRUE;
  1045. pSigOpt = (SIGOPT *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1046. poi = (OPTINFO *)GetWindowLongPtr(hwnd, DWLP_USER);
  1047. hwndList = GetDlgItem(hwnd, IDC_SIG_LIST);
  1048. switch (msg)
  1049. {
  1050. case WM_INITDIALOG:
  1051. Assert(poi == NULL);
  1052. poi = (OPTINFO *)(((PROPSHEETPAGE *)lParam)->lParam);
  1053. Assert(poi != NULL);
  1054. SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)poi);
  1055. pSigOpt = InitSigOpt();
  1056. Assert(pSigOpt != NULL);
  1057. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)pSigOpt);
  1058. InitSigDlg(hwnd, pSigOpt, poi);
  1059. PropSheet_UnChanged(GetParent(hwnd), hwnd);
  1060. break;
  1061. case WM_DESTROY:
  1062. FreeIcon(hwnd, IDC_SIG_SETTINGS_ICON);
  1063. FreeIcon(hwnd, IDC_SIGLIST_ICON);
  1064. FreeIcon(hwnd, IDC_SIG_EDIT_ICON);
  1065. if (pSigOpt != NULL)
  1066. {
  1067. DeinitSigOpt(pSigOpt);
  1068. SetWindowLongPtr(hwnd, GWLP_USERDATA, 0);
  1069. }
  1070. SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR)g_SigListUnicodeProc);
  1071. g_SigListUnicodeProc = NULL;
  1072. break;
  1073. case WM_HELP:
  1074. case WM_CONTEXTMENU:
  1075. return OnContextHelp(hwnd, msg, wParam, lParam, g_rgCtxMapSigs);
  1076. case WM_COMMAND:
  1077. if (poi == NULL)
  1078. break;
  1079. code = HIWORD(wParam);
  1080. id = LOWORD(wParam);
  1081. switch (id)
  1082. {
  1083. case IDC_FILE_EDIT:
  1084. case IDC_TEXT_EDIT:
  1085. if (code == EN_CHANGE && !pSigOpt->fNoDirty)
  1086. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1087. break;
  1088. case IDC_FILE_RADIO:
  1089. case IDC_TEXT_RADIO:
  1090. if (code == BN_CLICKED)
  1091. {
  1092. EnableSigWindows(hwnd, id == IDC_TEXT_RADIO);
  1093. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1094. }
  1095. break;
  1096. case IDC_ADDREPLY_CHECK:
  1097. case IDC_SIGBOTTOM_CHECK:
  1098. if (code == BN_CLICKED)
  1099. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1100. break;
  1101. case IDC_ADDSIG_CHECK:
  1102. if (code == BN_CLICKED)
  1103. {
  1104. fEnable = (IsDlgButtonChecked(hwnd, IDC_ADDSIG_CHECK) == BST_CHECKED);
  1105. EnableWindow(GetDlgItem(hwnd, IDC_ADDREPLY_CHECK), fEnable);
  1106. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1107. }
  1108. break;
  1109. case IDC_NEW_BUTTON:
  1110. if (code == BN_CLICKED)
  1111. {
  1112. if (SUCCEEDED(HandleNewSig(hwnd, pSigOpt)))
  1113. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1114. }
  1115. break;
  1116. case IDC_REMOVE_BUTTON:
  1117. if (code == BN_CLICKED)
  1118. {
  1119. if (SUCCEEDED(HandleDeleteSig(hwnd, pSigOpt)))
  1120. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1121. }
  1122. break;
  1123. case IDC_RENAME_BUTTON:
  1124. if (code == BN_CLICKED)
  1125. {
  1126. i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED);
  1127. Assert(i >= 0);
  1128. SetFocus(hwndList);
  1129. ListView_EditLabel(hwndList, i);
  1130. }
  1131. break;
  1132. case IDC_DEFAULT_BUTTON:
  1133. if (code == BN_CLICKED)
  1134. {
  1135. i = GetItemIndex(hwndList, -1);
  1136. if (i != pSigOpt->iDefSig)
  1137. {
  1138. SetDefault(hwndList, pSigOpt->iDefSig, i);
  1139. pSigOpt->iDefSig = i;
  1140. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1141. EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), FALSE);
  1142. if (!IsWindowEnabled(GetFocus()))
  1143. SetFocus(GetDlgItem(hwnd, IDC_NEW_BUTTON));
  1144. }
  1145. }
  1146. break;
  1147. case IDC_BROWSE_BUTTON:
  1148. if (code == BN_CLICKED)
  1149. {
  1150. if (S_OK == HandleBrowseButton(hwnd))
  1151. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1152. }
  1153. break;
  1154. case IDC_ADV_BUTTON:
  1155. if (code == BN_CLICKED)
  1156. {
  1157. pSigOpt->iSelSig = GetItemIndex(hwndList, -1);
  1158. Assert(pSigOpt->iSelSig >= 0);
  1159. if (IDOK == DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddAdvSig), hwnd, AdvSigDlgProc, (LPARAM)pSigOpt))
  1160. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1161. }
  1162. break;
  1163. }
  1164. break;
  1165. case WM_NOTIFY:
  1166. pnmh = (LPNMHDR)lParam;
  1167. switch (pnmh->code)
  1168. {
  1169. case PSN_APPLY:
  1170. Assert(poi != NULL);
  1171. cSig = ListView_GetItemCount(hwndList);
  1172. if (cSig > 0)
  1173. {
  1174. i = GetItemIndex(hwndList, -1);
  1175. hr = ValidateSig(hwnd, hwndList, i, pSigOpt);
  1176. if (hr != S_OK)
  1177. {
  1178. SetDlgMsgResult(hwnd, WM_NOTIFY, PSNRET_INVALID_NOCHANGEPAGE);
  1179. return (PSNRET_INVALID_NOCHANGEPAGE);
  1180. }
  1181. }
  1182. dw = 0;
  1183. if (cSig > 0 &&
  1184. IsDlgButtonChecked(hwnd, IDC_ADDSIG_CHECK) == BST_CHECKED)
  1185. {
  1186. dw = SIGFLAG_AUTONEW;
  1187. if (IsDlgButtonChecked(hwnd, IDC_ADDREPLY_CHECK) == BST_UNCHECKED)
  1188. dw |= SIGFLAG_AUTOREPLY;
  1189. }
  1190. ISetDwOption(poi->pOpt, OPT_SIGNATURE_FLAGS, dw, NULL, 0);
  1191. SaveSigs(hwnd, pSigOpt);
  1192. PropSheet_UnChanged(GetParent(hwnd), hwnd);
  1193. break;
  1194. case LVN_BEGINLABELEDITW:
  1195. {
  1196. HWND hwndEdit;
  1197. hwndEdit = ListView_GetEditControl(hwndList);
  1198. if(hwndEdit)
  1199. g_SigRenameEditUnicodeProc = (WNDPROC) SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)SigRenameEditANSIProc);
  1200. }
  1201. case LVN_BEGINLABELEDITA:
  1202. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE);
  1203. break;
  1204. case LVN_ENDLABELEDITW:
  1205. {
  1206. HWND hwndEdit;
  1207. hwndEdit = ListView_GetEditControl(hwndList);
  1208. if(hwndEdit)
  1209. {
  1210. SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)g_SigRenameEditUnicodeProc);
  1211. g_SigRenameEditUnicodeProc = NULL;
  1212. }
  1213. }
  1214. case LVN_ENDLABELEDITA:
  1215. hr = HandleSigRename(hwnd, (LV_DISPINFO *)pnmh, pSigOpt);
  1216. if (hr == S_OK)
  1217. SetPageDirty(poi, hwnd, PAGE_SIGS);
  1218. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, hr == S_OK);
  1219. break;
  1220. case LVN_ITEMCHANGING:
  1221. pnmlv = (NM_LISTVIEW *)pnmh;
  1222. if (!!(pnmlv->uOldState & LVIS_FOCUSED) &&
  1223. !(pnmlv->uNewState & LVIS_FOCUSED) &&
  1224. pnmlv->iItem != -1)
  1225. {
  1226. // item is losing selection
  1227. if (pSigOpt->iInvalidSig != -1)
  1228. {
  1229. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE);
  1230. pSigOpt->iInvalidSig = -1;
  1231. break;
  1232. }
  1233. hr = ValidateSig(hwnd, hwndList, (int)pnmlv->lParam, pSigOpt);
  1234. SetWindowLongPtr(hwnd, DWLP_MSGRESULT, hr != S_OK);
  1235. if (hr != S_OK)
  1236. pSigOpt->iInvalidSig = pnmlv->iItem;
  1237. }
  1238. break;
  1239. case LVN_ITEMCHANGED:
  1240. pnmlv = (NM_LISTVIEW *)pnmh;
  1241. if (!(pnmlv->uOldState & LVIS_FOCUSED) &&
  1242. !!(pnmlv->uNewState & LVIS_FOCUSED) &&
  1243. pnmlv->iItem != -1)
  1244. {
  1245. // item is becoming the selection
  1246. Assert(pSigOpt->iInvalidSig == -1);
  1247. pSigOpt->fNoDirty = TRUE;
  1248. pSig = &pSigOpt->pSig[pnmlv->lParam];
  1249. if (pSig->type == SIGTYPE_TEXT)
  1250. {
  1251. CheckDlgButton(hwnd, IDC_TEXT_RADIO, BST_CHECKED);
  1252. SetDlgItemText(hwnd, IDC_TEXT_EDIT, pSig->szText != NULL ? pSig->szText : c_szEmpty);
  1253. CheckDlgButton(hwnd, IDC_FILE_RADIO, BST_UNCHECKED);
  1254. SetDlgItemText(hwnd, IDC_FILE_EDIT, c_szEmpty);
  1255. }
  1256. else
  1257. {
  1258. Assert(pSig->type == SIGTYPE_FILE);
  1259. CheckDlgButton(hwnd, IDC_FILE_RADIO, BST_CHECKED);
  1260. SetDlgItemTextWrapW(hwnd, IDC_FILE_EDIT, pSig->wszFile != NULL ? pSig->wszFile : c_wszEmpty);
  1261. CheckDlgButton(hwnd, IDC_TEXT_RADIO, BST_UNCHECKED);
  1262. SetDlgItemText(hwnd, IDC_TEXT_EDIT, c_szEmpty);
  1263. }
  1264. EnableSigWindows(hwnd, pSig->type == SIGTYPE_TEXT);
  1265. EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), pSigOpt->iDefSig != GetItemIndex(hwndList, pnmlv->iItem));
  1266. pSigOpt->fNoDirty = FALSE;
  1267. }
  1268. break;
  1269. default:
  1270. break;
  1271. }
  1272. break;
  1273. default:
  1274. fRet = FALSE;
  1275. break;
  1276. }
  1277. return(fRet);
  1278. }
  1279. HRESULT FillSignatureMenu(HMENU hmenu, LPCSTR szAcct)
  1280. {
  1281. HRESULT hr;
  1282. int i, cSig, iDef;
  1283. char *psz, szDef[MAXSIGID], sz[MAXSIGNAME + 64], szT[64];
  1284. IOptionBucket *pSig;
  1285. PROPVARIANT var;
  1286. Assert(g_pSigMgr != NULL);
  1287. hr = g_pSigMgr->GetSignatureCount(&cSig);
  1288. Assert(SUCCEEDED(hr));
  1289. Assert(cSig > 0);
  1290. hr = g_pSigMgr->GetDefaultSignature(szDef, ARRAYSIZE(szDef));
  1291. Assert(SUCCEEDED(hr));
  1292. Assert(szDef[0] != 0);
  1293. iDef = -1;
  1294. for (i = 0; i < cSig; i++)
  1295. {
  1296. hr = g_pSigMgr->EnumSignatures(i, &pSig);
  1297. if (hr != S_OK)
  1298. break;
  1299. Assert(pSig != NULL);
  1300. if (iDef == -1)
  1301. {
  1302. hr = pSig->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0);
  1303. Assert(SUCCEEDED(hr));
  1304. Assert(var.vt == VT_LPSTR);
  1305. Assert(var.pszVal != NULL);
  1306. if (0 == lstrcmpi(szDef, var.pszVal))
  1307. iDef = i;
  1308. MemFree(var.pszVal);
  1309. }
  1310. hr = pSig->GetProperty(MAKEPROPSTRING(SIG_NAME), &var, 0);
  1311. Assert(SUCCEEDED(hr));
  1312. Assert(var.vt == VT_LPSTR);
  1313. Assert(var.pszVal != NULL);
  1314. if (i == iDef)
  1315. {
  1316. AthLoadString(idsDefaultAccount, szT, ARRAYSIZE(szT));
  1317. wnsprintf(sz, ARRAYSIZE(sz), c_szSpaceCatFmt, var.pszVal, szT);
  1318. psz = sz;
  1319. }
  1320. else
  1321. {
  1322. psz = var.pszVal;
  1323. }
  1324. InsertMenu(hmenu, i, MF_BYPOSITION | MF_STRING, ID_SIGNATURE_FIRST + i, psz);
  1325. MemFree(var.pszVal);
  1326. }
  1327. Assert(iDef != -1);
  1328. return(S_OK);
  1329. }
  1330. HRESULT InitSigPopupMenu(HMENU hmenu, LPCSTR szAcct)
  1331. {
  1332. int cSig;
  1333. HRESULT hr;
  1334. Assert(g_pSigMgr != NULL);
  1335. hr = g_pSigMgr->GetSignatureCount(&cSig);
  1336. if (FAILED(hr))
  1337. return(hr);
  1338. if (cSig > 0)
  1339. {
  1340. HMENU hmenuOld = NULL, hmenuSig = NULL;
  1341. MENUITEMINFO mii;
  1342. ZeroMemory(&mii, sizeof(mii));
  1343. mii.cbSize = sizeof(MENUITEMINFO);
  1344. mii.fMask = MIIM_SUBMENU;
  1345. SideAssert(GetMenuItemInfo(hmenu, ID_INSERT_SIGNATURE, FALSE, &mii));
  1346. hmenuOld = mii.hSubMenu;
  1347. if (cSig > 1)
  1348. {
  1349. hmenuSig = CreatePopupMenu();
  1350. Assert(hmenuSig != NULL);
  1351. hr = FillSignatureMenu(hmenuSig, szAcct);
  1352. if (FAILED(hr))
  1353. return(hr);
  1354. }
  1355. mii.hSubMenu = hmenuSig;
  1356. // Set the menu item
  1357. SideAssert(SetMenuItemInfo(hmenu, ID_INSERT_SIGNATURE, FALSE, &mii));
  1358. if (hmenuOld != NULL)
  1359. DestroyMenu(hmenuOld);
  1360. }
  1361. return(S_OK);
  1362. }
  1363. void DeinitSigPopupMenu(HWND hwnd)
  1364. {
  1365. HMENU hmenu;
  1366. MENUITEMINFO mii;
  1367. hmenu = GetMenu(hwnd);
  1368. if (hmenu != NULL)
  1369. {
  1370. ZeroMemory(&mii, sizeof(mii));
  1371. mii.cbSize = sizeof(MENUITEMINFO);
  1372. mii.fMask = MIIM_SUBMENU;
  1373. if (GetMenuItemInfo(hmenu, ID_INSERT_SIGNATURE, FALSE, &mii) &&
  1374. mii.hSubMenu != NULL)
  1375. DestroyMenu(mii.hSubMenu);
  1376. }
  1377. }
  1378. HRESULT GetSigFromCmd(int id, char * pszID, DWORD cchSize)
  1379. {
  1380. HRESULT hr;
  1381. IOptionBucket *pSig;
  1382. PROPVARIANT var;
  1383. Assert(pszID != NULL);
  1384. Assert(id >= ID_SIGNATURE_FIRST && id <= ID_SIGNATURE_LAST);
  1385. id = id - ID_SIGNATURE_FIRST;
  1386. Assert(g_pSigMgr != NULL);
  1387. hr = g_pSigMgr->EnumSignatures(id, &pSig);
  1388. if (hr != S_OK)
  1389. return(E_FAIL);
  1390. Assert(pSig != NULL);
  1391. hr = pSig->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0);
  1392. Assert(SUCCEEDED(hr));
  1393. Assert(var.vt == VT_LPSTR);
  1394. Assert(var.pszVal != NULL);
  1395. StrCpyN(pszID, var.pszVal, cchSize);
  1396. MemFree(var.pszVal);
  1397. return(S_OK);
  1398. }
  1399. void InitAcctSig(SIGOPT *pSigOpt)
  1400. {
  1401. IImnEnumAccounts *pEnum;
  1402. IImnAccount *pAcct;
  1403. ACCTSIG *pAcctSig;
  1404. HRESULT hr;
  1405. ULONG cAcct;
  1406. SIG *pSig;
  1407. int i, cmp;
  1408. PROPVARIANT var;
  1409. char szSigID[MAXSIGID];
  1410. Assert(pSigOpt != NULL);
  1411. if (pSigOpt->pAcctSig != NULL)
  1412. return;
  1413. Assert(g_pAcctMan != NULL);
  1414. if (SUCCEEDED(g_pAcctMan->Enumerate(SRV_MAIL | SRV_NNTP, &pEnum)))
  1415. {
  1416. Assert(pEnum != NULL);
  1417. hr = pEnum->GetCount(&cAcct);
  1418. Assert(SUCCEEDED(hr));
  1419. if (cAcct > 0 &&
  1420. MemAlloc((void **)&pSigOpt->pAcctSig, cAcct * sizeof(ACCTSIG)))
  1421. {
  1422. for (cAcct = 0, pAcctSig = pSigOpt->pAcctSig; SUCCEEDED(pEnum->GetNext(&pAcct)); cAcct++, pAcctSig++)
  1423. {
  1424. Assert(pAcct != NULL);
  1425. pAcctSig->pAcct = pAcct;
  1426. pAcctSig->iSig = -1;
  1427. hr = pAcct->GetAccountType(&pAcctSig->type);
  1428. Assert(SUCCEEDED(hr));
  1429. if (SUCCEEDED(pAcct->GetPropSz(pAcctSig->type == ACCT_MAIL ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE, szSigID, ARRAYSIZE(szSigID))) &&
  1430. !FIsEmpty(szSigID))
  1431. {
  1432. for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++)
  1433. {
  1434. if (pSig->pBckt != NULL)
  1435. {
  1436. hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0);
  1437. Assert(SUCCEEDED(hr));
  1438. Assert(var.vt == VT_LPSTR);
  1439. Assert(var.pszVal != NULL);
  1440. cmp = lstrcmpi(szSigID, var.pszVal);
  1441. MemFree(var.pszVal);
  1442. if (cmp == 0)
  1443. {
  1444. pAcctSig->iSig = i;
  1445. break;
  1446. }
  1447. }
  1448. }
  1449. }
  1450. }
  1451. pSigOpt->cAcctSig = cAcct;
  1452. }
  1453. pEnum->Release();
  1454. }
  1455. }
  1456. void InitAdvSigDlg(HWND hwnd, SIGOPT *pSigOpt)
  1457. {
  1458. SIG *pSig;
  1459. ACCTSIG *pAcctSig;
  1460. char *psz, *pszT;
  1461. int cch, i, index;
  1462. LV_COLUMN lvc;
  1463. RECT rc;
  1464. HIMAGELIST himl;
  1465. HWND hwndT, hwndList;
  1466. LV_ITEM lvi;
  1467. Assert(pSigOpt != NULL);
  1468. Assert(pSigOpt->iSelSig < pSigOpt->cSig);
  1469. pSig = &pSigOpt->pSig[pSigOpt->iSelSig];
  1470. Assert(!pSig->fDelete);
  1471. InitAcctSig(pSigOpt);
  1472. hwndT = GetDlgItem(hwnd, IDC_ADVSIG_STATIC);
  1473. cch = GetWindowTextLength(hwndT) + 1;
  1474. DWORD cchTotal = (cch * 2 + MAXSIGNAME);
  1475. if (!MemAlloc((void **)&psz, cchTotal))
  1476. return;
  1477. pszT = psz + cch;
  1478. GetWindowText(hwndT, psz, cchTotal);
  1479. wnsprintf(pszT, (cchTotal - cch), psz, pSig->szName);
  1480. SetWindowText(hwndT, pszT);
  1481. hwndList = GetDlgItem(hwnd, IDC_ACCOUNT_LIST);
  1482. ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES);
  1483. GetClientRect(hwndList, &rc);
  1484. rc.right = rc.right - GetSystemMetrics(SM_CXVSCROLL);
  1485. rc.right = rc.right / 2;
  1486. lvc.mask = LVCF_WIDTH | LVCF_TEXT;
  1487. lvc.cx = rc.right;
  1488. lvc.pszText = psz;
  1489. // account column
  1490. AthLoadString(idsAccount, psz, cch);
  1491. ListView_InsertColumn(hwndList, 0, &lvc);
  1492. // type column
  1493. AthLoadString(idsType, psz, cch);
  1494. ListView_InsertColumn(hwndList, 1, &lvc);
  1495. // Add Folders Imagelist
  1496. himl = ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbFolders), 16, 0, RGB(255, 0, 255));
  1497. ListView_SetImageList(hwndList, himl, LVSIL_SMALL);
  1498. for (i = 0, pAcctSig = pSigOpt->pAcctSig; i < pSigOpt->cAcctSig; i++, pAcctSig++)
  1499. {
  1500. Assert(pAcctSig->pAcct != NULL);
  1501. if (SUCCEEDED(pAcctSig->pAcct->GetPropSz(AP_ACCOUNT_NAME, psz, cch)))
  1502. {
  1503. lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM;
  1504. lvi.iItem = i;
  1505. lvi.iSubItem = 0;
  1506. lvi.pszText = psz;
  1507. lvi.iImage = (pAcctSig->type == ACCT_MAIL) ? iMailServer : iNewsServer;
  1508. lvi.lParam = i;
  1509. lvi.stateMask = LVIS_STATEIMAGEMASK;
  1510. index = ListView_InsertItem(hwndList, &lvi);
  1511. Assert(index != -1);
  1512. AthLoadString((pAcctSig->type == ACCT_MAIL) ? idsMail : idsNews, psz, cch);
  1513. lvi.mask = LVIF_TEXT;
  1514. lvi.iItem = index;
  1515. lvi.iSubItem = 1;
  1516. lvi.pszText = psz;
  1517. ListView_SetItem(hwndList, &lvi);
  1518. if (pAcctSig->iSig == pSigOpt->iSelSig)
  1519. ListView_SetItemState(hwndList, index, INDEXTOSTATEIMAGEMASK(2), LVIS_STATEIMAGEMASK); // 1 unchecked, 2 checked
  1520. }
  1521. }
  1522. if (pSigOpt->cAcctSig > 0)
  1523. ListView_SetItemState(hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED);
  1524. MemFree(psz);
  1525. }
  1526. void SaveAcctSigSettings(HWND hwnd, SIGOPT *pSigOpt)
  1527. {
  1528. int i, iAcctSig;
  1529. ACCTSIG *pAcctSig;
  1530. HWND hwndList;
  1531. BOOL fCheck;
  1532. Assert(pSigOpt != NULL);
  1533. hwndList = GetDlgItem(hwnd, IDC_ACCOUNT_LIST);
  1534. for (i = 0; i < pSigOpt->cAcctSig; i++)
  1535. {
  1536. iAcctSig = GetItemIndex(hwndList, i);
  1537. Assert(iAcctSig >= 0 && iAcctSig < pSigOpt->cAcctSig);
  1538. pAcctSig = &pSigOpt->pAcctSig[iAcctSig];
  1539. fCheck = ListView_GetCheckState(hwndList, i);
  1540. if (pSigOpt->iSelSig == pAcctSig->iSig)
  1541. {
  1542. if (!fCheck)
  1543. pAcctSig->iSig = -1;
  1544. }
  1545. else
  1546. {
  1547. if (fCheck)
  1548. pAcctSig->iSig = pSigOpt->iSelSig;
  1549. }
  1550. }
  1551. }
  1552. INT_PTR CALLBACK AdvSigDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  1553. {
  1554. SIGOPT *pSigOpt;
  1555. WORD id;
  1556. HWND hwndList;
  1557. BOOL fRet = TRUE;
  1558. pSigOpt = (SIGOPT *)GetWindowLongPtr(hwnd, GWLP_USERDATA);
  1559. hwndList = GetDlgItem(hwnd, IDC_ACCOUNT_LIST);
  1560. switch (msg)
  1561. {
  1562. case WM_INITDIALOG:
  1563. Assert(pSigOpt == NULL);
  1564. pSigOpt = (SIGOPT *)lParam;
  1565. Assert(pSigOpt != NULL);
  1566. SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)pSigOpt);
  1567. Assert(pSigOpt->iSelSig >= 0 && pSigOpt->iSelSig < pSigOpt->cSig);
  1568. InitAdvSigDlg(hwnd, pSigOpt);
  1569. break;
  1570. case WM_COMMAND:
  1571. id = LOWORD(wParam);
  1572. switch (id)
  1573. {
  1574. case IDOK:
  1575. SaveAcctSigSettings(hwnd, pSigOpt);
  1576. // fall through...
  1577. case IDCANCEL:
  1578. EndDialog(hwnd, id);
  1579. break;
  1580. default:
  1581. break;
  1582. }
  1583. break;
  1584. default:
  1585. fRet = FALSE;
  1586. break;
  1587. }
  1588. return(fRet);
  1589. }