#include "pch.hxx" #include #include #include #include #include #include #include #include #include "sigs.h" #include "mimeolep.h" #include "demand.h" #include "menures.h" #include typedef struct tagSIG { IOptionBucket *pBckt; char szName[MAXSIGNAME]; LPWSTR wszFile; LPSTR szText; DWORD type; BOOL fDelete; } SIG; typedef struct tagACCTSIG { IImnAccount *pAcct; ACCTTYPE type; int iSig; } ACCTSIG; typedef struct tagSIGOPT { SIG *pSig; int cSig; int cSigBuf; ACCTSIG *pAcctSig; int cAcctSig; int iDefSig; int iInvalidSig; // needed for commctrl BOOL fNoDirty; int iSelSig; // used by the advanced sig dialog } SIGOPT; HRESULT ValidateSig(HWND hwnd, HWND hwndList, int iSig, SIGOPT *pSigOpt); INT_PTR CALLBACK AdvSigDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); void EnableSigOptions(HWND hwnd, BOOL fEnable); CSignatureManager *g_pSigMgr = NULL; const OPTIONINFO c_rgSigInfo[] = { {SIG_ID, VT_LPSTR, 0, NULL, NULL, 0, 0, MAXSIGID - 1, 0}, {SIG_NAME, VT_LPSTR, 0, c_szSigName, NULL, 0, 0, MAXSIGNAME - 1, 0}, {SIG_FILE, VT_LPWSTR, 0, c_szSigFile, NULL, 0, 0, MAX_PATH - 1, 0}, {SIG_TEXT, VT_LPSTR, 0, c_szSigText, NULL, 0, 0, MAXSIGTEXT - 1, 0}, {SIG_TYPE, VT_UI4, 0, c_szSigType, (LPCSTR)SIGTYPE_TEXT, 0, 0, 0, 0} }; HRESULT InitSignatureManager(HKEY hkey, LPCSTR szRegRoot) { HRESULT hr; Assert(g_pSigMgr == NULL); Assert(g_pOpt != NULL); g_pSigMgr = new CSignatureManager(hkey, szRegRoot); if (g_pSigMgr == NULL) hr = E_OUTOFMEMORY; else hr = S_OK; return(hr); } HRESULT DeinitSignatureManager() { if (g_pSigMgr != NULL) { g_pSigMgr->Release(); g_pSigMgr = NULL; } return(S_OK); } CSignatureManager::CSignatureManager(HKEY hkey, LPCSTR pszRegKeyRoot) { m_cRef = 1; m_fInit = FALSE; m_hkey = hkey; wnsprintf(m_szRegRoot, ARRAYSIZE(m_szRegRoot), c_szPathFileFmt, pszRegKeyRoot, c_szSigs); m_pBckt = NULL; m_cBckt = 0; m_cBcktBuf = 0; } CSignatureManager::~CSignatureManager(void) { int i; if (m_pBckt != NULL) { for (i = 0; i < m_cBckt; i++) { if (m_pBckt[i].pBckt != NULL) m_pBckt[i].pBckt->Release(); } MemFree(m_pBckt); } } ULONG CSignatureManager::AddRef(void) { return((ULONG)InterlockedIncrement(&m_cRef)); } ULONG CSignatureManager::Release(void) { LONG cRef = InterlockedDecrement(&m_cRef); if (0 == cRef) delete this; return((ULONG)cRef); } #define CSIGREALLOC 8 HRESULT CSignatureManager::Initialize() { HKEY hkey; HRESULT hr; BOOL fDef; DWORD cSig, cSigBuf, cb, i; SIGBUCKET *pBckt; hr = S_OK; if (!m_fInit) { if (ERROR_SUCCESS == RegCreateKeyEx(m_hkey, m_szRegRoot, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hkey, &cb)) { fDef = FALSE; cb = sizeof(m_szDefSigID); RegQueryValueEx(hkey, c_szRegDefSig, NULL, &i, (LPBYTE)m_szDefSigID, &cb); if (ERROR_SUCCESS == RegQueryInfoKey (hkey, NULL, NULL, NULL, &cSig, NULL, NULL, NULL, NULL, NULL, NULL, NULL)) { cSigBuf = cSig + CSIGREALLOC; cb = cSigBuf * sizeof(SIGBUCKET); if (!MemAlloc((void **)&m_pBckt, cb)) { hr = E_OUTOFMEMORY; } else { ZeroMemory(m_pBckt, cb); m_cBcktBuf = cSigBuf; for (i = 0, pBckt = m_pBckt; i < cSig; i++, pBckt++) { cb = sizeof(pBckt->szID); if (ERROR_SUCCESS != RegEnumKeyEx(hkey, i, pBckt->szID, &cb, NULL, NULL, NULL, NULL)) { // TODO: what if this fails???? break; } if (!fDef && *m_szDefSigID != 0 && 0 == lstrcmpi(m_szDefSigID, pBckt->szID)) fDef = TRUE; m_cBckt++; } } } if (!fDef && m_cBckt > 0) { // there was no default or it was bogus, so just set it to the 1st sig StrCpyN(m_szDefSigID, m_pBckt->szID, ARRAYSIZE(m_szDefSigID)); } RegCloseKey(hkey); } if (SUCCEEDED(hr)) m_fInit = TRUE; } return(hr); } HRESULT CSignatureManager::GetBucket(SIGBUCKET *pSigBckt) { OPTBCKTINIT init; char szKey[MAX_PATH]; IOptionBucketEx *pBcktEx; HRESULT hr; PROPVARIANT var; Assert(pSigBckt != NULL); Assert(pSigBckt->pBckt == NULL); hr = CreateOptionBucketEx(&pBcktEx); if (FAILED(hr)) return(hr); ZeroMemory(&init, sizeof(OPTBCKTINIT)); init.rgInfo = c_rgSigInfo; init.cInfo = ARRAYSIZE(c_rgSigInfo); init.hkey = m_hkey; wnsprintf(szKey, ARRAYSIZE(szKey), c_szPathFileFmt, m_szRegRoot, pSigBckt->szID); init.pszRegKeyBase = szKey; var.vt = VT_LPSTR; var.pszVal = pSigBckt->szID; if (FAILED(hr = pBcktEx->Initialize(&init)) || FAILED(hr = pBcktEx->SetProperty(MAKEPROPSTRING(SIG_ID), &var, 0))) { pBcktEx->Release(); return(hr); } hr = pBcktEx->QueryInterface(IID_IOptionBucket, (void **)&pSigBckt->pBckt); Assert(SUCCEEDED(hr)); pBcktEx->Release(); return(hr); } HRESULT CSignatureManager::GetSignature(LPCSTR szID, IOptionBucket **ppBckt) { HRESULT hr; SIGBUCKET *pBckt; int i; Assert(szID != NULL); Assert(ppBckt != NULL); AssertSz(m_cBckt, "Someone didn't check to see if we had any sigs"); *ppBckt = NULL; hr = Initialize(); if (SUCCEEDED(hr)) { hr = E_FAIL; for (i = 0, pBckt = m_pBckt; i < m_cBckt; i++, pBckt++) { if (0 == lstrcmpi(pBckt->szID, szID)) { hr = S_OK; if (pBckt->pBckt == NULL) hr = GetBucket(pBckt); if (SUCCEEDED(hr)) { *ppBckt = pBckt->pBckt; (*ppBckt)->AddRef(); } break; } } } return(hr); } HRESULT CSignatureManager::GetSignatureCount(int *pcSig) { HRESULT hr; Assert(pcSig != NULL); hr = Initialize(); if (SUCCEEDED(hr)) *pcSig = m_cBckt; return(hr); } HRESULT CSignatureManager::EnumSignatures(int index, IOptionBucket **ppBckt) { HRESULT hr; SIGBUCKET *pBckt; Assert(ppBckt != NULL); *ppBckt = NULL; hr = Initialize(); if (SUCCEEDED(hr)) { if (index >= m_cBckt) return(S_FALSE); hr = S_OK; pBckt = &m_pBckt[index]; if (pBckt->pBckt == NULL) hr = GetBucket(pBckt); if (SUCCEEDED(hr)) { *ppBckt = pBckt->pBckt; (*ppBckt)->AddRef(); } } return(hr); } static const char c_szIDFmt[] = "%08lx"; HRESULT CSignatureManager::CreateSignature(IOptionBucket **ppBckt) { HRESULT hr; int cAlloc; DWORD id, dwDisp; HKEY hkey; SIGBUCKET *pBckt; char szKey[MAX_PATH], szID[MAXSIGID]; Assert(ppBckt != NULL); *ppBckt = NULL; hr = Initialize(); if (SUCCEEDED(hr)) { hr = E_FAIL; if (m_cBckt == m_cBcktBuf) { cAlloc = m_cBcktBuf + CSIGREALLOC; if (!MemRealloc((void **)&m_pBckt, cAlloc * sizeof(SIGBUCKET))) return(E_OUTOFMEMORY); m_cBcktBuf = cAlloc; ZeroMemory(&m_pBckt[m_cBckt], CSIGREALLOC * sizeof(SIGBUCKET)); } pBckt = &m_pBckt[m_cBckt]; id = 0; while (TRUE) { wnsprintf(szID, ARRAYSIZE(szID), c_szIDFmt, id); wnsprintf(szKey, ARRAYSIZE(szKey), c_szPathFileFmt, m_szRegRoot, szID); if (ERROR_SUCCESS == RegCreateKeyEx(m_hkey, szKey, 0, NULL, REG_OPTION_NON_VOLATILE, KEY_READ, NULL, &hkey, &dwDisp)) { RegCloseKey(hkey); if (dwDisp == REG_OPENED_EXISTING_KEY) { id++; continue; } StrCpyN(pBckt->szID, szID, ARRAYSIZE(pBckt->szID)); hr = GetBucket(pBckt); if (SUCCEEDED(hr)) { m_cBckt++; *ppBckt = pBckt->pBckt; (*ppBckt)->AddRef(); } else { RegDeleteKey(m_hkey, szKey); } } break; } } return(hr); } HRESULT CSignatureManager::DeleteSignature(LPCSTR szID) { HRESULT hr; char sz[MAX_PATH], szSigID[MAXSIGID]; int i; SIGBUCKET *pBckt; ACCTTYPE type; IImnAccount *pAcct; IImnEnumAccounts *pEnum; BOOL fDeletingDefault = FALSE; hr = Initialize(); if (SUCCEEDED(hr)) { hr = E_FAIL; for (i = 0, pBckt = m_pBckt; i < m_cBckt; i++, pBckt++) { if (0 == lstrcmpi(pBckt->szID, szID)) { fDeletingDefault = (0 == lstrcmpi(pBckt->szID, m_szDefSigID)); wnsprintf(sz, ARRAYSIZE(sz), c_szPathFileFmt, m_szRegRoot, szID); if (ERROR_SUCCESS == SHDeleteKey(m_hkey, sz)) { if (pBckt->pBckt != NULL) { pBckt->pBckt->Release(); pBckt->pBckt = NULL; } if (i + 1 < m_cBckt) MoveMemory(&m_pBckt[i], &m_pBckt[i + 1], (m_cBckt - (i + 1)) * sizeof(SIGBUCKET)); m_cBckt--; m_pBckt[m_cBckt].pBckt = NULL; hr = S_OK; Assert(g_pAcctMan != NULL); if (SUCCEEDED(g_pAcctMan->Enumerate(SRV_MAIL | SRV_NNTP, &pEnum))) { Assert(pEnum != NULL); while (SUCCEEDED(pEnum->GetNext(&pAcct))) { Assert(pAcct != NULL); hr = pAcct->GetAccountType(&type); Assert(SUCCEEDED(hr)); if (SUCCEEDED(pAcct->GetPropSz(type == ACCT_MAIL ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE, szSigID, ARRAYSIZE(szSigID))) && 0 == lstrcmpi(szSigID, szID)) { pAcct->SetPropSz(type == ACCT_MAIL ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE, NULL); pAcct->SaveChanges(); } pAcct->Release(); } pEnum->Release(); } } break; } } if (fDeletingDefault) { if (m_cBckt > 0) SetDefaultSignature(m_pBckt->szID); else SetDefaultSignature(""); } } return(hr); } HRESULT CSignatureManager::GetDefaultSignature(LPSTR pszID, DWORD cchSize) { HRESULT hr; AssertSz(m_cBckt, "Someone didn't check to see if we had any sigs"); hr = Initialize(); if (SUCCEEDED(hr)) StrCpyN(pszID, m_szDefSigID, cchSize); return(hr); } HRESULT CSignatureManager::SetDefaultSignature(LPCSTR szID) { HRESULT hr; Assert(szID != NULL); Assert(lstrlen(szID) < MAXSIGID); hr = Initialize(); if (SUCCEEDED(hr)) { if (ERROR_SUCCESS == SHSetValue(m_hkey, m_szRegRoot, c_szRegDefSig, REG_SZ, szID, lstrlen(szID) + 1)) StrCpyN(m_szDefSigID, szID, ARRAYSIZE(m_szDefSigID)); else hr = E_FAIL; } return(hr); } // TODO: error handling would be useful SIGOPT *InitSigOpt(void) { HRESULT hr; int i, cSig; SIG *pSig; char szDef[MAXSIGID]; PROPVARIANT var; SIGOPT *pSigOpt = NULL; Assert(g_pSigMgr != NULL); if (MemAlloc((void **)&pSigOpt, sizeof(SIGOPT))) { ZeroMemory(pSigOpt, sizeof(SIGOPT)); pSigOpt->iDefSig = -1; pSigOpt->iInvalidSig = -1; hr = g_pSigMgr->GetSignatureCount(&cSig); Assert(SUCCEEDED(hr)); if (cSig > 0) { pSigOpt->cSigBuf = cSig + CSIGREALLOC; if (MemAlloc((void **)&pSigOpt->pSig, pSigOpt->cSigBuf * sizeof(SIG))) { ZeroMemory(pSigOpt->pSig, pSigOpt->cSigBuf * sizeof(SIG)); hr = g_pSigMgr->GetDefaultSignature(szDef, ARRAYSIZE(szDef)); Assert(SUCCEEDED(hr)); Assert(szDef[0] != 0); for (i = 0, pSig = pSigOpt->pSig; i < cSig; i++, pSig++) { hr = g_pSigMgr->EnumSignatures(i, &pSig->pBckt); if (hr != S_OK) break; Assert(pSig->pBckt != NULL); if (pSigOpt->iDefSig == -1) { hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_LPSTR); Assert(var.pszVal != NULL); if (0 == lstrcmpi(szDef, var.pszVal)) pSigOpt->iDefSig = i; MemFree(var.pszVal); } hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_NAME), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_LPSTR); Assert(var.pszVal != NULL); StrCpyN(pSig->szName, var.pszVal, ARRAYSIZE(pSig->szName)); MemFree(var.pszVal); hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_TYPE), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_UI4); pSig->type = var.ulVal; if (pSig->type == SIGTYPE_TEXT) { hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_TEXT), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_LPSTR); Assert(var.pszVal != NULL); pSig->szText = var.pszVal; } else { Assert(pSig->type == SIGTYPE_FILE); hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_FILE), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_LPWSTR); Assert(var.pwszVal != NULL); pSig->wszFile = var.pwszVal; } pSigOpt->cSig++; } } } } return(pSigOpt); } void DeinitSigOpt(SIGOPT *pSigOpt) { int i; SIG *pSig; ACCTSIG *pAcctSig; if (pSigOpt != NULL) { if (pSigOpt->pSig != NULL) { for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++) { if (pSig->wszFile != NULL) MemFree(pSig->wszFile); if (pSig->szText != NULL) MemFree(pSig->szText); if (pSig->pBckt != NULL) pSig->pBckt->Release(); } MemFree(pSigOpt->pSig); } if (pSigOpt->pAcctSig != NULL) { for (i = 0, pAcctSig = pSigOpt->pAcctSig; i < pSigOpt->cAcctSig; i++, pAcctSig++) { if (pAcctSig->pAcct != NULL) pAcctSig->pAcct->Release(); } MemFree(pSigOpt->pAcctSig); } MemFree(pSigOpt); } } int InsertSig(HWND hwndList, SIG *pSig, int i) { int index; LV_ITEM lvi; Assert(pSig != NULL); lvi.mask = LVIF_TEXT | LVIF_PARAM; lvi.iItem = i; lvi.iSubItem = 0; lvi.pszText = pSig->szName; lvi.lParam = i; index = ListView_InsertItem(hwndList, &lvi); Assert(index != -1); return(index); } void SetDefault(HWND hwndList, int iOldDef, int iNewDef) { char sz[64]; LV_FINDINFO lvfi; int i; if (iOldDef >= 0) { lvfi.flags = LVFI_PARAM; lvfi.lParam = iOldDef; i = ListView_FindItem(hwndList, -1, &lvfi); ListView_SetItemText(hwndList, i, 1, (LPSTR)c_szEmpty); } lvfi.flags = LVFI_PARAM; lvfi.lParam = iNewDef; i = ListView_FindItem(hwndList, -1, &lvfi); AthLoadString(idsDefaultSignature, sz, ARRAYSIZE(sz)); ListView_SetItemText(hwndList, i, 1, sz); } void EnableSignatureWindows(HWND hwnd, BOOL fEnable) { EnableWindow(GetDlgItem(hwnd, IDC_REMOVE_BUTTON), fEnable); EnableWindow(GetDlgItem(hwnd, IDC_RENAME_BUTTON), fEnable); EnableWindow(GetDlgItem(hwnd, IDC_TEXT_RADIO), fEnable); EnableWindow(GetDlgItem(hwnd, IDC_TEXT_EDIT), fEnable); EnableWindow(GetDlgItem(hwnd, IDC_FILE_RADIO), fEnable); EnableWindow(GetDlgItem(hwnd, IDC_FILE_EDIT), fEnable); EnableWindow(GetDlgItem(hwnd, IDC_BROWSE_BUTTON), fEnable); EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), fEnable); EnableWindow(GetDlgItem(hwnd, IDC_ADV_BUTTON), fEnable); if (!fEnable) { CheckDlgButton(hwnd, IDC_TEXT_RADIO, BST_UNCHECKED); SetDlgItemText(hwnd, IDC_TEXT_EDIT, c_szEmpty); CheckDlgButton(hwnd, IDC_FILE_RADIO, BST_UNCHECKED); SetDlgItemText(hwnd, IDC_FILE_EDIT, c_szEmpty); if (!IsWindowEnabled(GetFocus())) SetFocus(GetDlgItem(hwnd, IDC_NEW_BUTTON)); } } WNDPROC g_SigListUnicodeProc = NULL; LRESULT CALLBACK SigListANSIProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return(CallWindowProc(g_SigListUnicodeProc, hwnd, msg, wParam, lParam)); } void InitSigDlg(HWND hwnd, SIGOPT *pSigOpt, OPTINFO *poi) { HWND hwndList, hwndT; RECT rc; int i; DWORD dw; LV_COLUMN lvc; SIG *pSig; Assert(pSigOpt != NULL); hwndT = GetDlgItem(hwnd, IDC_TEXT_EDIT); SetIntlFont(hwndT); SendMessage(hwndT, EM_LIMITTEXT, MAXSIGTEXT - 1, 0); hwndT = GetDlgItem(hwnd, IDC_FILE_EDIT); SetIntlFont(hwndT); SendMessage(hwndT, EM_LIMITTEXT, MAX_PATH - 1, 0); dw = IDwGetOption(poi->pOpt, OPT_SIGNATURE_FLAGS); CheckDlgButton(hwnd, IDC_ADDSIG_CHECK, !!(dw & SIGFLAG_AUTONEW) ? BST_CHECKED : BST_UNCHECKED); CheckDlgButton(hwnd, IDC_ADDREPLY_CHECK, !(dw & SIGFLAG_AUTOREPLY) ? BST_CHECKED : BST_UNCHECKED); if (!(dw & SIGFLAG_AUTONEW)) EnableWindow(GetDlgItem(hwnd, IDC_ADDREPLY_CHECK), FALSE); hwndList = GetDlgItem(hwnd, IDC_SIG_LIST); g_SigListUnicodeProc = (WNDPROC) SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR)SigListANSIProc); GetClientRect(hwndList, &rc); rc.right = rc.right - GetSystemMetrics(SM_CXVSCROLL); rc.right = rc.right / 2; lvc.mask = LVCF_WIDTH; lvc.cx = rc.right; ListView_InsertColumn(hwndList, 0, &lvc); ListView_InsertColumn(hwndList, 1, &lvc); for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++) InsertSig(hwndList, pSig, i); if (pSigOpt->iDefSig >= 0) SetDefault(hwndList, -1, pSigOpt->iDefSig); if (pSigOpt->cSig > 0) { ListView_SetItemState(hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); } else { EnableSignatureWindows(hwnd, FALSE); EnableSigOptions(hwnd, FALSE); } // Pictures HICON hIcon; hIcon = ImageList_GetIcon(poi->himl, ID_SIGNATURES, ILD_TRANSPARENT); SendDlgItemMessage(hwnd, IDC_SIG_SETTINGS_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon); hIcon = ImageList_GetIcon(poi->himl, ID_SIG_LIST, ILD_TRANSPARENT); SendDlgItemMessage(hwnd, IDC_SIGLIST_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon); hIcon = ImageList_GetIcon(poi->himl, ID_SIG_EDIT, ILD_TRANSPARENT); SendDlgItemMessage(hwnd, IDC_SIG_EDIT_ICON, STM_SETIMAGE, IMAGE_ICON, (LPARAM) hIcon); } BOOL IsUniqueSigName(LPCSTR szName, SIGOPT *pSigOpt) { int i; SIG *pSig; for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++) { if (!pSig->fDelete && 0 == lstrcmpi(szName, pSig->szName)) return(FALSE); } return(TRUE); } int GetItemIndex(HWND hwndList, int i) { LV_ITEM lvi; if (i == -1) { // get the selected item's index i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED); Assert(i >= 0); } lvi.iItem = i; lvi.iSubItem = 0; lvi.mask = LVIF_PARAM; ListView_GetItem(hwndList, &lvi); return((int)(INT_PTR)(lvi.lParam)); } HRESULT HandleNewSig(HWND hwnd, SIGOPT *pSigOpt) { HRESULT hr; SIG *pSig; char sz[MAXSIGNAME]; int i, cSig, cAlloc; HWND hwndList; hwndList = GetDlgItem(hwnd, IDC_SIG_LIST); cSig = ListView_GetItemCount(hwndList); if (cSig > 0) { i = GetItemIndex(hwndList, -1); if (i >= 0) { hr = ValidateSig(hwnd, hwndList, i, pSigOpt); if (FAILED(hr)) return(E_FAIL); } } if (pSigOpt->cSig == pSigOpt->cSigBuf) { cAlloc = pSigOpt->cSigBuf + CSIGREALLOC; if (!MemRealloc((void **)&pSigOpt->pSig, cAlloc * sizeof(SIG))) return(E_OUTOFMEMORY); ZeroMemory(&pSigOpt->pSig[pSigOpt->cSig], CSIGREALLOC * sizeof(SIG)); pSigOpt->cSigBuf = cAlloc; } pSig = &pSigOpt->pSig[pSigOpt->cSig]; AthLoadString(idsSigNameFmt, sz, ARRAYSIZE(sz)); for (i = 1; i < 10000; i++) { wnsprintf(pSig->szName, ARRAYSIZE(pSig->szName), sz, i); if (IsUniqueSigName(pSig->szName, pSigOpt)) break; } if (i == 10000) return(E_FAIL); pSig->type = SIGTYPE_TEXT; i = InsertSig(hwndList, pSig, pSigOpt->cSig); if (pSigOpt->iDefSig == -1) { SetDefault(hwndList, -1, pSigOpt->cSig); pSigOpt->iDefSig = pSigOpt->cSig; } pSigOpt->cSig++; if (cSig == 0) { EnableSignatureWindows(hwnd, TRUE); EnableSigOptions(hwnd, TRUE); } EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), pSigOpt->iDefSig != GetItemIndex(hwndList, i)); ListView_SetItemState(hwndList, i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); ListView_EnsureVisible(hwndList, i, FALSE); SetFocus(GetDlgItem(hwnd, IDC_TEXT_EDIT)); return(S_OK); } HRESULT HandleDeleteSig(HWND hwnd, SIGOPT *pSigOpt) { int i, iSig, iNewSel, cSig; HWND hwndList; SIG *pSig; hwndList = GetDlgItem(hwnd, IDC_SIG_LIST); i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED); Assert(i >= 0); iSig = GetItemIndex(hwndList, i); pSig = &pSigOpt->pSig[iSig]; Assert(!pSig->fDelete); pSig->fDelete = TRUE; ListView_DeleteItem(hwndList, i); cSig = ListView_GetItemCount(hwndList); if (cSig == 0) iNewSel = -1; else if (i == 0) iNewSel = 0; else iNewSel = i - 1; Assert(pSigOpt->iDefSig >= 0); if (iSig == pSigOpt->iDefSig) { if (iNewSel >= 0) { iSig = GetItemIndex(hwndList, iNewSel); SetDefault(hwndList, -1, iSig); pSigOpt->iDefSig = iSig; EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), FALSE); } else { pSigOpt->iDefSig = -1; } } if (iNewSel >= 0) { ListView_SetItemState(hwndList, iNewSel, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); ListView_EnsureVisible(hwndList, iNewSel, FALSE); } else { EnableSignatureWindows(hwnd, FALSE); EnableSigOptions(hwnd, FALSE); } return(S_OK); } HRESULT HandleSigRename(HWND hwnd, LV_DISPINFO *pdi, SIGOPT *pSigOpt) { HWND hwndList; SIG *pSig, *pSigT; LPSTR pszText = NULL; HRESULT hr = S_OK; int i; Assert(pdi != NULL); Assert(pSigOpt != NULL); IF_TRUEEXIT((pdi->item.pszText == NULL || FIsEmpty(pdi->item.pszText)), S_FALSE); if(IsWindowUnicode(hwnd)) pszText = PszToANSI(CP_ACP, (WCHAR*)(pdi->item.pszText)); else pszText = StrDupA(pdi->item.pszText); IF_NULLEXIT(pszText); IF_TRUEEXIT((lstrlen(pszText) >= MAXSIGNAME), S_FALSE); pSig = &pSigOpt->pSig[pdi->item.lParam]; Assert(!pSig->fDelete); Assert(pSig->szName[0] != 0); IF_TRUEEXIT((0 == lstrcmpi(pSig->szName, pszText)), S_FALSE); for (i = 0, pSigT = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSigT++) { if (pSigT->fDelete) continue; IF_TRUEEXIT((0 == lstrcmpi(pSigT->szName, pszText)), S_FALSE); } StrCpyN(pSig->szName, pszText, ARRAYSIZE(pSig->szName)); exit: MemFree(pszText); return hr; } static const int c_rgidsFilter[] = { idsTextFileFilter, idsHtmlFileFilter, idsAllFilesFilter }; HRESULT HandleBrowseButton(HWND hwnd) { OPENFILENAMEW ofnw; WCHAR wszFilter[MAX_PATH], wszFile[MAX_PATH], wszDir[MAX_PATH]; HRESULT hr; int cch; LPWSTR pwszFile; hr = S_FALSE; *wszFilter = 0; *wszFile = 0; ZeroMemory(&ofnw, sizeof(ofnw)); ofnw.lStructSize = sizeof(ofnw); cch = GetDlgItemTextWrapW(hwnd, IDC_FILE_EDIT, wszDir, ARRAYSIZE(wszDir)); if (cch > 0) { if (PathIsDirectoryW(wszDir)) { ofnw.lpstrInitialDir = wszDir; } else if (PathFileExistsW(wszDir)) { pwszFile = PathFindFileNameW(wszDir); if (pwszFile != NULL) StrCpyNW(wszFile, pwszFile, ARRAYSIZE(wszFile)); *pwszFile = 0; if (*wszDir != 0) ofnw.lpstrInitialDir = wszDir; } else if (PathIsFileSpecW(wszDir)) { StrCpyNW(wszFile, wszDir, ARRAYSIZE(wszFile)); } } CombineFiltersW((int *)c_rgidsFilter, ARRAYSIZE(c_rgidsFilter), wszFilter); ofnw.hwndOwner = hwnd; ofnw.lpstrFile = wszFile; ofnw.lpstrFilter = wszFilter; ofnw.nMaxFile = ARRAYSIZE(wszFile); ofnw.Flags = OFN_FILEMUSTEXIST | OFN_HIDEREADONLY | OFN_NONETWORKBUTTON | OFN_NOCHANGEDIR | OFN_EXPLORER; if (HrAthGetFileNameW(&ofnw, TRUE)==S_OK) { SetDlgItemTextWrapW(hwnd, IDC_FILE_EDIT, wszFile); hr = S_OK; } return(hr); } HRESULT ValidateSig(HWND hwnd, HWND hwndList, int iSig, SIGOPT *pSigOpt) { SIG *pSig; BOOL fText; HWND hwndT; int cch, id, i; char **ppsz, *psz; Assert(pSigOpt != NULL); Assert(iSig < pSigOpt->cSig); pSig = &pSigOpt->pSig[iSig]; if (pSig->fDelete) return(S_OK); fText = (IsDlgButtonChecked(hwnd, IDC_TEXT_RADIO) == BST_CHECKED); id = fText ? IDC_TEXT_EDIT : IDC_FILE_EDIT; hwndT = GetDlgItem(hwnd, id); cch = GetWindowTextLength(hwndT); if (cch == 0) { i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED); ListView_SetItemState(hwndList, i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); InvalidOptionProp(hwnd, id, fText ? idsEnterSigText : idsEnterSigFile, iddOpt_Signature); return(E_FAIL); } cch++; if (!fText) { WCHAR *pwsz = NULL; if (!MemAlloc((void **)&pwsz, cch * sizeof(*pwsz))) return(E_OUTOFMEMORY); GetWindowTextWrapW(hwndT, pwsz, cch); if (!PathFileExistsW(pwsz) || PathIsDirectoryW(pwsz)) { MemFree(pwsz); i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED); ListView_SetItemState(hwndList, i, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); InvalidOptionProp(hwnd, id, idsSigFileNoExistError, iddOpt_Signature); return(E_FAIL); } else { //Free the previous sig file MemFree(pSig->wszFile); pSig->wszFile = pwsz; } } else { if (!MemAlloc((void **)&psz, cch)) return(E_OUTOFMEMORY); GetWindowText(hwndT, psz, cch); //Free the previous sig text MemFree(pSig->szText); pSig->szText = psz; } pSig->type = fText ? SIGTYPE_TEXT : SIGTYPE_FILE; return(S_OK); } HRESULT SaveSigs(HWND hwnd, SIGOPT *pSigOpt) { int cSigT, cSig, i; SIG *pSig; ACCTSIG *pAcctSig; PROPVARIANT var; HRESULT hr; HWND hwndList; char *szSigID; Assert(pSigOpt != NULL); Assert(g_pSigMgr != NULL); hwndList = GetDlgItem(hwnd, IDC_SIG_LIST); cSig = ListView_GetItemCount(hwndList); cSigT = 0; for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++) { if (pSig->fDelete) { if (pSig->pBckt != NULL) { if (SUCCEEDED(pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0)) && var.pszVal != NULL) { g_pSigMgr->DeleteSignature(var.pszVal); MemFree(var.pszVal); } } continue; } else { if (pSig->pBckt == NULL) { hr = g_pSigMgr->CreateSignature(&pSig->pBckt); Assert(SUCCEEDED(hr)); Assert(pSig->pBckt != NULL); } if (pSigOpt->iDefSig == i) { if (SUCCEEDED(pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0)) && var.pszVal) { g_pSigMgr->SetDefaultSignature(var.pszVal); MemFree(var.pszVal); } } var.vt = VT_LPSTR; var.pszVal = pSig->szName; hr = pSig->pBckt->SetProperty(MAKEPROPSTRING(SIG_NAME), &var, 0); AssertSz(SUCCEEDED(hr), "Sig name failed to be set"); var.vt = VT_UI4; var.ulVal = pSig->type; hr = pSig->pBckt->SetProperty(MAKEPROPSTRING(SIG_TYPE), &var, 0); AssertSz(SUCCEEDED(hr), "Sig type failed to be set"); var.vt = VT_LPSTR; AssertSz(((SIGTYPE_TEXT == pSig->type) ? (NULL != pSig->szText) : TRUE), "Text should be set."); var.pszVal = (SIGTYPE_TEXT == pSig->type) ? pSig->szText : (LPSTR)c_szEmpty; hr = pSig->pBckt->SetProperty(MAKEPROPSTRING(SIG_TEXT), &var, 0); AssertSz(SUCCEEDED(hr), "Sig text failed to be set"); var.vt = VT_LPWSTR; var.pwszVal = (pSig->type == SIGTYPE_FILE) ? pSig->wszFile : (LPWSTR)c_wszEmpty; hr = pSig->pBckt->SetProperty(MAKEPROPSTRING(SIG_FILE), &var, 0); AssertSz(SUCCEEDED(hr), "Sig filename failed to be set"); cSigT++; } } Assert(cSig == cSigT); for (i = 0, pAcctSig = pSigOpt->pAcctSig; i < pSigOpt->cAcctSig; i++, pAcctSig++) { szSigID = NULL; if (pAcctSig->iSig >= 0) { pSig = &pSigOpt->pSig[pAcctSig->iSig]; if (!pSig->fDelete) { hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.pszVal != NULL); szSigID = var.pszVal; } } hr = pAcctSig->pAcct->SetPropSz(pAcctSig->type == ACCT_MAIL ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE, szSigID); Assert(SUCCEEDED(hr)); hr = pAcctSig->pAcct->SaveChanges(); Assert(SUCCEEDED(hr)); if (szSigID != NULL) MemFree(szSigID); } return(S_OK); } void EnableSigWindows(HWND hwnd, BOOL fText) { HWND focus; focus = GetFocus(); EnableWindow(GetDlgItem(hwnd, IDC_TEXT_EDIT), fText); EnableWindow(GetDlgItem(hwnd, IDC_FILE_EDIT), !fText); EnableWindow(GetDlgItem(hwnd, IDC_BROWSE_BUTTON), !fText); // don't disable button that has the focus if (!IsWindowEnabled(focus)) SetFocus(GetDlgItem(hwnd, fText ? IDC_TEXT_EDIT : IDC_FILE_EDIT)); } void EnableSigOptions(HWND hwnd, BOOL fEnable) { HWND hwndT; hwndT = GetDlgItem(hwnd, IDC_ADDSIG_CHECK); EnableWindow(hwndT, fEnable); if (fEnable) fEnable = (SendMessage(hwndT, BM_GETCHECK, 0, 0) == BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_ADDREPLY_CHECK), fEnable); } static const HELPMAP g_rgCtxMapSigs[] = { {IDC_ADDSIG_CHECK, 353569}, {IDC_ADDREPLY_CHECK, 35610}, {IDC_SIG_LIST, 35594}, {IDC_NEW_BUTTON, 35591}, {IDC_REMOVE_BUTTON, 35592}, {IDC_RENAME_BUTTON, 35593}, {IDC_TEXT_EDIT, 35595}, {IDC_FILE_EDIT, 35600}, {IDC_DEFAULT_BUTTON, 35596}, {IDC_ADV_BUTTON, 35597}, {IDC_BROWSE_BUTTON, 35605}, {idcStatic1, IDH_NEWS_COMM_GROUPBOX}, {idcStatic2, IDH_NEWS_COMM_GROUPBOX}, {idcStatic3, IDH_NEWS_COMM_GROUPBOX}, {idcStatic4, IDH_NEWS_COMM_GROUPBOX}, {idcStatic5, IDH_NEWS_COMM_GROUPBOX}, {idcStatic6, IDH_NEWS_COMM_GROUPBOX}, {IDC_SIG_SETTINGS_ICON, IDH_NEWS_COMM_GROUPBOX}, {IDC_SIGLIST_ICON, IDH_NEWS_COMM_GROUPBOX}, {IDC_SIG_EDIT_ICON, IDH_NEWS_COMM_GROUPBOX}, {0, 0} }; WNDPROC g_SigRenameEditUnicodeProc = NULL; LRESULT CALLBACK SigRenameEditANSIProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { return(CallWindowProc(g_SigRenameEditUnicodeProc, hwnd, msg, wParam, lParam)); } INT_PTR CALLBACK SigDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { SIGOPT *pSigOpt; WORD code, id; SIG *pSig; int i, cSig; DWORD dw; OPTINFO *poi; LPNMHDR pnmh; NM_LISTVIEW *pnmlv; HRESULT hr; HWND hwndList; BOOL fEnable, fRet = TRUE; pSigOpt = (SIGOPT *)GetWindowLongPtr(hwnd, GWLP_USERDATA); poi = (OPTINFO *)GetWindowLongPtr(hwnd, DWLP_USER); hwndList = GetDlgItem(hwnd, IDC_SIG_LIST); switch (msg) { case WM_INITDIALOG: Assert(poi == NULL); poi = (OPTINFO *)(((PROPSHEETPAGE *)lParam)->lParam); Assert(poi != NULL); SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM)poi); pSigOpt = InitSigOpt(); Assert(pSigOpt != NULL); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)pSigOpt); InitSigDlg(hwnd, pSigOpt, poi); PropSheet_UnChanged(GetParent(hwnd), hwnd); break; case WM_DESTROY: FreeIcon(hwnd, IDC_SIG_SETTINGS_ICON); FreeIcon(hwnd, IDC_SIGLIST_ICON); FreeIcon(hwnd, IDC_SIG_EDIT_ICON); if (pSigOpt != NULL) { DeinitSigOpt(pSigOpt); SetWindowLongPtr(hwnd, GWLP_USERDATA, 0); } SetWindowLongPtr(hwndList, GWLP_WNDPROC, (LONG_PTR)g_SigListUnicodeProc); g_SigListUnicodeProc = NULL; break; case WM_HELP: case WM_CONTEXTMENU: return OnContextHelp(hwnd, msg, wParam, lParam, g_rgCtxMapSigs); case WM_COMMAND: if (poi == NULL) break; code = HIWORD(wParam); id = LOWORD(wParam); switch (id) { case IDC_FILE_EDIT: case IDC_TEXT_EDIT: if (code == EN_CHANGE && !pSigOpt->fNoDirty) SetPageDirty(poi, hwnd, PAGE_SIGS); break; case IDC_FILE_RADIO: case IDC_TEXT_RADIO: if (code == BN_CLICKED) { EnableSigWindows(hwnd, id == IDC_TEXT_RADIO); SetPageDirty(poi, hwnd, PAGE_SIGS); } break; case IDC_ADDREPLY_CHECK: case IDC_SIGBOTTOM_CHECK: if (code == BN_CLICKED) SetPageDirty(poi, hwnd, PAGE_SIGS); break; case IDC_ADDSIG_CHECK: if (code == BN_CLICKED) { fEnable = (IsDlgButtonChecked(hwnd, IDC_ADDSIG_CHECK) == BST_CHECKED); EnableWindow(GetDlgItem(hwnd, IDC_ADDREPLY_CHECK), fEnable); SetPageDirty(poi, hwnd, PAGE_SIGS); } break; case IDC_NEW_BUTTON: if (code == BN_CLICKED) { if (SUCCEEDED(HandleNewSig(hwnd, pSigOpt))) SetPageDirty(poi, hwnd, PAGE_SIGS); } break; case IDC_REMOVE_BUTTON: if (code == BN_CLICKED) { if (SUCCEEDED(HandleDeleteSig(hwnd, pSigOpt))) SetPageDirty(poi, hwnd, PAGE_SIGS); } break; case IDC_RENAME_BUTTON: if (code == BN_CLICKED) { i = ListView_GetNextItem(hwndList, -1, LVNI_ALL | LVNI_FOCUSED); Assert(i >= 0); SetFocus(hwndList); ListView_EditLabel(hwndList, i); } break; case IDC_DEFAULT_BUTTON: if (code == BN_CLICKED) { i = GetItemIndex(hwndList, -1); if (i != pSigOpt->iDefSig) { SetDefault(hwndList, pSigOpt->iDefSig, i); pSigOpt->iDefSig = i; SetPageDirty(poi, hwnd, PAGE_SIGS); EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), FALSE); if (!IsWindowEnabled(GetFocus())) SetFocus(GetDlgItem(hwnd, IDC_NEW_BUTTON)); } } break; case IDC_BROWSE_BUTTON: if (code == BN_CLICKED) { if (S_OK == HandleBrowseButton(hwnd)) SetPageDirty(poi, hwnd, PAGE_SIGS); } break; case IDC_ADV_BUTTON: if (code == BN_CLICKED) { pSigOpt->iSelSig = GetItemIndex(hwndList, -1); Assert(pSigOpt->iSelSig >= 0); if (IDOK == DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddAdvSig), hwnd, AdvSigDlgProc, (LPARAM)pSigOpt)) SetPageDirty(poi, hwnd, PAGE_SIGS); } break; } break; case WM_NOTIFY: pnmh = (LPNMHDR)lParam; switch (pnmh->code) { case PSN_APPLY: Assert(poi != NULL); cSig = ListView_GetItemCount(hwndList); if (cSig > 0) { i = GetItemIndex(hwndList, -1); hr = ValidateSig(hwnd, hwndList, i, pSigOpt); if (hr != S_OK) { SetDlgMsgResult(hwnd, WM_NOTIFY, PSNRET_INVALID_NOCHANGEPAGE); return (PSNRET_INVALID_NOCHANGEPAGE); } } dw = 0; if (cSig > 0 && IsDlgButtonChecked(hwnd, IDC_ADDSIG_CHECK) == BST_CHECKED) { dw = SIGFLAG_AUTONEW; if (IsDlgButtonChecked(hwnd, IDC_ADDREPLY_CHECK) == BST_UNCHECKED) dw |= SIGFLAG_AUTOREPLY; } ISetDwOption(poi->pOpt, OPT_SIGNATURE_FLAGS, dw, NULL, 0); SaveSigs(hwnd, pSigOpt); PropSheet_UnChanged(GetParent(hwnd), hwnd); break; case LVN_BEGINLABELEDITW: { HWND hwndEdit; hwndEdit = ListView_GetEditControl(hwndList); if(hwndEdit) g_SigRenameEditUnicodeProc = (WNDPROC) SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)SigRenameEditANSIProc); } case LVN_BEGINLABELEDITA: SetWindowLongPtr(hwnd, DWLP_MSGRESULT, FALSE); break; case LVN_ENDLABELEDITW: { HWND hwndEdit; hwndEdit = ListView_GetEditControl(hwndList); if(hwndEdit) { SetWindowLongPtr(hwndEdit, GWLP_WNDPROC, (LONG_PTR)g_SigRenameEditUnicodeProc); g_SigRenameEditUnicodeProc = NULL; } } case LVN_ENDLABELEDITA: hr = HandleSigRename(hwnd, (LV_DISPINFO *)pnmh, pSigOpt); if (hr == S_OK) SetPageDirty(poi, hwnd, PAGE_SIGS); SetWindowLongPtr(hwnd, DWLP_MSGRESULT, hr == S_OK); break; case LVN_ITEMCHANGING: pnmlv = (NM_LISTVIEW *)pnmh; if (!!(pnmlv->uOldState & LVIS_FOCUSED) && !(pnmlv->uNewState & LVIS_FOCUSED) && pnmlv->iItem != -1) { // item is losing selection if (pSigOpt->iInvalidSig != -1) { SetWindowLongPtr(hwnd, DWLP_MSGRESULT, TRUE); pSigOpt->iInvalidSig = -1; break; } hr = ValidateSig(hwnd, hwndList, (int)pnmlv->lParam, pSigOpt); SetWindowLongPtr(hwnd, DWLP_MSGRESULT, hr != S_OK); if (hr != S_OK) pSigOpt->iInvalidSig = pnmlv->iItem; } break; case LVN_ITEMCHANGED: pnmlv = (NM_LISTVIEW *)pnmh; if (!(pnmlv->uOldState & LVIS_FOCUSED) && !!(pnmlv->uNewState & LVIS_FOCUSED) && pnmlv->iItem != -1) { // item is becoming the selection Assert(pSigOpt->iInvalidSig == -1); pSigOpt->fNoDirty = TRUE; pSig = &pSigOpt->pSig[pnmlv->lParam]; if (pSig->type == SIGTYPE_TEXT) { CheckDlgButton(hwnd, IDC_TEXT_RADIO, BST_CHECKED); SetDlgItemText(hwnd, IDC_TEXT_EDIT, pSig->szText != NULL ? pSig->szText : c_szEmpty); CheckDlgButton(hwnd, IDC_FILE_RADIO, BST_UNCHECKED); SetDlgItemText(hwnd, IDC_FILE_EDIT, c_szEmpty); } else { Assert(pSig->type == SIGTYPE_FILE); CheckDlgButton(hwnd, IDC_FILE_RADIO, BST_CHECKED); SetDlgItemTextWrapW(hwnd, IDC_FILE_EDIT, pSig->wszFile != NULL ? pSig->wszFile : c_wszEmpty); CheckDlgButton(hwnd, IDC_TEXT_RADIO, BST_UNCHECKED); SetDlgItemText(hwnd, IDC_TEXT_EDIT, c_szEmpty); } EnableSigWindows(hwnd, pSig->type == SIGTYPE_TEXT); EnableWindow(GetDlgItem(hwnd, IDC_DEFAULT_BUTTON), pSigOpt->iDefSig != GetItemIndex(hwndList, pnmlv->iItem)); pSigOpt->fNoDirty = FALSE; } break; default: break; } break; default: fRet = FALSE; break; } return(fRet); } HRESULT FillSignatureMenu(HMENU hmenu, LPCSTR szAcct) { HRESULT hr; int i, cSig, iDef; char *psz, szDef[MAXSIGID], sz[MAXSIGNAME + 64], szT[64]; IOptionBucket *pSig; PROPVARIANT var; Assert(g_pSigMgr != NULL); hr = g_pSigMgr->GetSignatureCount(&cSig); Assert(SUCCEEDED(hr)); Assert(cSig > 0); hr = g_pSigMgr->GetDefaultSignature(szDef, ARRAYSIZE(szDef)); Assert(SUCCEEDED(hr)); Assert(szDef[0] != 0); iDef = -1; for (i = 0; i < cSig; i++) { hr = g_pSigMgr->EnumSignatures(i, &pSig); if (hr != S_OK) break; Assert(pSig != NULL); if (iDef == -1) { hr = pSig->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_LPSTR); Assert(var.pszVal != NULL); if (0 == lstrcmpi(szDef, var.pszVal)) iDef = i; MemFree(var.pszVal); } hr = pSig->GetProperty(MAKEPROPSTRING(SIG_NAME), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_LPSTR); Assert(var.pszVal != NULL); if (i == iDef) { AthLoadString(idsDefaultAccount, szT, ARRAYSIZE(szT)); wnsprintf(sz, ARRAYSIZE(sz), c_szSpaceCatFmt, var.pszVal, szT); psz = sz; } else { psz = var.pszVal; } InsertMenu(hmenu, i, MF_BYPOSITION | MF_STRING, ID_SIGNATURE_FIRST + i, psz); MemFree(var.pszVal); } Assert(iDef != -1); return(S_OK); } HRESULT InitSigPopupMenu(HMENU hmenu, LPCSTR szAcct) { int cSig; HRESULT hr; Assert(g_pSigMgr != NULL); hr = g_pSigMgr->GetSignatureCount(&cSig); if (FAILED(hr)) return(hr); if (cSig > 0) { HMENU hmenuOld = NULL, hmenuSig = NULL; MENUITEMINFO mii; ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_SUBMENU; SideAssert(GetMenuItemInfo(hmenu, ID_INSERT_SIGNATURE, FALSE, &mii)); hmenuOld = mii.hSubMenu; if (cSig > 1) { hmenuSig = CreatePopupMenu(); Assert(hmenuSig != NULL); hr = FillSignatureMenu(hmenuSig, szAcct); if (FAILED(hr)) return(hr); } mii.hSubMenu = hmenuSig; // Set the menu item SideAssert(SetMenuItemInfo(hmenu, ID_INSERT_SIGNATURE, FALSE, &mii)); if (hmenuOld != NULL) DestroyMenu(hmenuOld); } return(S_OK); } void DeinitSigPopupMenu(HWND hwnd) { HMENU hmenu; MENUITEMINFO mii; hmenu = GetMenu(hwnd); if (hmenu != NULL) { ZeroMemory(&mii, sizeof(mii)); mii.cbSize = sizeof(MENUITEMINFO); mii.fMask = MIIM_SUBMENU; if (GetMenuItemInfo(hmenu, ID_INSERT_SIGNATURE, FALSE, &mii) && mii.hSubMenu != NULL) DestroyMenu(mii.hSubMenu); } } HRESULT GetSigFromCmd(int id, char * pszID, DWORD cchSize) { HRESULT hr; IOptionBucket *pSig; PROPVARIANT var; Assert(pszID != NULL); Assert(id >= ID_SIGNATURE_FIRST && id <= ID_SIGNATURE_LAST); id = id - ID_SIGNATURE_FIRST; Assert(g_pSigMgr != NULL); hr = g_pSigMgr->EnumSignatures(id, &pSig); if (hr != S_OK) return(E_FAIL); Assert(pSig != NULL); hr = pSig->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_LPSTR); Assert(var.pszVal != NULL); StrCpyN(pszID, var.pszVal, cchSize); MemFree(var.pszVal); return(S_OK); } void InitAcctSig(SIGOPT *pSigOpt) { IImnEnumAccounts *pEnum; IImnAccount *pAcct; ACCTSIG *pAcctSig; HRESULT hr; ULONG cAcct; SIG *pSig; int i, cmp; PROPVARIANT var; char szSigID[MAXSIGID]; Assert(pSigOpt != NULL); if (pSigOpt->pAcctSig != NULL) return; Assert(g_pAcctMan != NULL); if (SUCCEEDED(g_pAcctMan->Enumerate(SRV_MAIL | SRV_NNTP, &pEnum))) { Assert(pEnum != NULL); hr = pEnum->GetCount(&cAcct); Assert(SUCCEEDED(hr)); if (cAcct > 0 && MemAlloc((void **)&pSigOpt->pAcctSig, cAcct * sizeof(ACCTSIG))) { for (cAcct = 0, pAcctSig = pSigOpt->pAcctSig; SUCCEEDED(pEnum->GetNext(&pAcct)); cAcct++, pAcctSig++) { Assert(pAcct != NULL); pAcctSig->pAcct = pAcct; pAcctSig->iSig = -1; hr = pAcct->GetAccountType(&pAcctSig->type); Assert(SUCCEEDED(hr)); if (SUCCEEDED(pAcct->GetPropSz(pAcctSig->type == ACCT_MAIL ? AP_SMTP_SIGNATURE : AP_NNTP_SIGNATURE, szSigID, ARRAYSIZE(szSigID))) && !FIsEmpty(szSigID)) { for (i = 0, pSig = pSigOpt->pSig; i < pSigOpt->cSig; i++, pSig++) { if (pSig->pBckt != NULL) { hr = pSig->pBckt->GetProperty(MAKEPROPSTRING(SIG_ID), &var, 0); Assert(SUCCEEDED(hr)); Assert(var.vt == VT_LPSTR); Assert(var.pszVal != NULL); cmp = lstrcmpi(szSigID, var.pszVal); MemFree(var.pszVal); if (cmp == 0) { pAcctSig->iSig = i; break; } } } } } pSigOpt->cAcctSig = cAcct; } pEnum->Release(); } } void InitAdvSigDlg(HWND hwnd, SIGOPT *pSigOpt) { SIG *pSig; ACCTSIG *pAcctSig; char *psz, *pszT; int cch, i, index; LV_COLUMN lvc; RECT rc; HIMAGELIST himl; HWND hwndT, hwndList; LV_ITEM lvi; Assert(pSigOpt != NULL); Assert(pSigOpt->iSelSig < pSigOpt->cSig); pSig = &pSigOpt->pSig[pSigOpt->iSelSig]; Assert(!pSig->fDelete); InitAcctSig(pSigOpt); hwndT = GetDlgItem(hwnd, IDC_ADVSIG_STATIC); cch = GetWindowTextLength(hwndT) + 1; DWORD cchTotal = (cch * 2 + MAXSIGNAME); if (!MemAlloc((void **)&psz, cchTotal)) return; pszT = psz + cch; GetWindowText(hwndT, psz, cchTotal); wnsprintf(pszT, (cchTotal - cch), psz, pSig->szName); SetWindowText(hwndT, pszT); hwndList = GetDlgItem(hwnd, IDC_ACCOUNT_LIST); ListView_SetExtendedListViewStyle(hwndList, LVS_EX_CHECKBOXES); GetClientRect(hwndList, &rc); rc.right = rc.right - GetSystemMetrics(SM_CXVSCROLL); rc.right = rc.right / 2; lvc.mask = LVCF_WIDTH | LVCF_TEXT; lvc.cx = rc.right; lvc.pszText = psz; // account column AthLoadString(idsAccount, psz, cch); ListView_InsertColumn(hwndList, 0, &lvc); // type column AthLoadString(idsType, psz, cch); ListView_InsertColumn(hwndList, 1, &lvc); // Add Folders Imagelist himl = ImageList_LoadBitmap(g_hLocRes, MAKEINTRESOURCE(idbFolders), 16, 0, RGB(255, 0, 255)); ListView_SetImageList(hwndList, himl, LVSIL_SMALL); for (i = 0, pAcctSig = pSigOpt->pAcctSig; i < pSigOpt->cAcctSig; i++, pAcctSig++) { Assert(pAcctSig->pAcct != NULL); if (SUCCEEDED(pAcctSig->pAcct->GetPropSz(AP_ACCOUNT_NAME, psz, cch))) { lvi.mask = LVIF_TEXT | LVIF_IMAGE | LVIF_PARAM; lvi.iItem = i; lvi.iSubItem = 0; lvi.pszText = psz; lvi.iImage = (pAcctSig->type == ACCT_MAIL) ? iMailServer : iNewsServer; lvi.lParam = i; lvi.stateMask = LVIS_STATEIMAGEMASK; index = ListView_InsertItem(hwndList, &lvi); Assert(index != -1); AthLoadString((pAcctSig->type == ACCT_MAIL) ? idsMail : idsNews, psz, cch); lvi.mask = LVIF_TEXT; lvi.iItem = index; lvi.iSubItem = 1; lvi.pszText = psz; ListView_SetItem(hwndList, &lvi); if (pAcctSig->iSig == pSigOpt->iSelSig) ListView_SetItemState(hwndList, index, INDEXTOSTATEIMAGEMASK(2), LVIS_STATEIMAGEMASK); // 1 unchecked, 2 checked } } if (pSigOpt->cAcctSig > 0) ListView_SetItemState(hwndList, 0, LVIS_SELECTED | LVIS_FOCUSED, LVIS_SELECTED | LVIS_FOCUSED); MemFree(psz); } void SaveAcctSigSettings(HWND hwnd, SIGOPT *pSigOpt) { int i, iAcctSig; ACCTSIG *pAcctSig; HWND hwndList; BOOL fCheck; Assert(pSigOpt != NULL); hwndList = GetDlgItem(hwnd, IDC_ACCOUNT_LIST); for (i = 0; i < pSigOpt->cAcctSig; i++) { iAcctSig = GetItemIndex(hwndList, i); Assert(iAcctSig >= 0 && iAcctSig < pSigOpt->cAcctSig); pAcctSig = &pSigOpt->pAcctSig[iAcctSig]; fCheck = ListView_GetCheckState(hwndList, i); if (pSigOpt->iSelSig == pAcctSig->iSig) { if (!fCheck) pAcctSig->iSig = -1; } else { if (fCheck) pAcctSig->iSig = pSigOpt->iSelSig; } } } INT_PTR CALLBACK AdvSigDlgProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { SIGOPT *pSigOpt; WORD id; HWND hwndList; BOOL fRet = TRUE; pSigOpt = (SIGOPT *)GetWindowLongPtr(hwnd, GWLP_USERDATA); hwndList = GetDlgItem(hwnd, IDC_ACCOUNT_LIST); switch (msg) { case WM_INITDIALOG: Assert(pSigOpt == NULL); pSigOpt = (SIGOPT *)lParam; Assert(pSigOpt != NULL); SetWindowLongPtr(hwnd, GWLP_USERDATA, (LPARAM)pSigOpt); Assert(pSigOpt->iSelSig >= 0 && pSigOpt->iSelSig < pSigOpt->cSig); InitAdvSigDlg(hwnd, pSigOpt); break; case WM_COMMAND: id = LOWORD(wParam); switch (id) { case IDOK: SaveAcctSigSettings(hwnd, pSigOpt); // fall through... case IDCANCEL: EndDialog(hwnd, id); break; default: break; } break; default: fRet = FALSE; break; } return(fRet); }