#include "pch.hxx" #include #include #include #include #include "exchacct.h" #include "acctman.h" #include "strconst.h" #include "demand.h" ASSERTDATA HKEY InetMailProfile(HKEY hkey); CMAPIAcctImport::CMAPIAcctImport() { m_cRef = 1; m_cInfo = 0; m_rgInfo = NULL; m_pAcctMan = NULL; } CMAPIAcctImport::~CMAPIAcctImport() { UINT i; if (m_rgInfo != NULL) { for (i = 0; i < m_cInfo; i++) { if (m_rgInfo[i].hkey != NULL) RegCloseKey(m_rgInfo[i].hkey); if (m_rgInfo[i].pAccount != NULL) m_rgInfo[i].pAccount->Release(); } MemFree(m_rgInfo); } if (m_pAcctMan != NULL) m_pAcctMan->Release(); } STDMETHODIMP CMAPIAcctImport::QueryInterface(REFIID riid, LPVOID *ppv) { if (ppv == NULL) return(E_INVALIDARG); *ppv = NULL; if (IID_IUnknown == riid) *ppv = (IAccountImport *)this; else if (IID_IAccountImport == riid) *ppv = (IAccountImport *)this; else if (IID_IAccountImport2 == riid) *ppv = (IAccountImport2 *)this; else return(E_NOINTERFACE); ((LPUNKNOWN)*ppv)->AddRef(); return(S_OK); } STDMETHODIMP_(ULONG) CMAPIAcctImport::AddRef() { return(++m_cRef); } STDMETHODIMP_(ULONG) CMAPIAcctImport::Release() { if (--m_cRef == 0) { delete this; return(0); } return(m_cRef); } const static char c_szRegNT[] = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles"; const static char c_szRegWin[] = "Software\\Microsoft\\Windows Messaging Subsystem\\Profiles"; HRESULT STDMETHODCALLTYPE CMAPIAcctImport::AutoDetect(DWORD *pcAcct, DWORD dwFlags) { LONG lRet; TCHAR szProfile[MAX_PATH]; HKEY hkey, hkeyProfile, hkeyInet; HRESULT hr; DWORD i, type, cb, cProfiles, dwMax; OSVERSIONINFO osinfo; BOOL fNT; IImnEnumAccounts *pEnumAccounts; IImnAccount *pAccount; if (pcAcct == NULL) return(E_INVALIDARG); hr = S_OK; *pcAcct = 0; cProfiles = 0; osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); GetVersionEx(&osinfo); fNT = (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT); if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, fNT ? c_szRegNT : c_szRegWin, 0, KEY_ALL_ACCESS, &hkey)) { if (ERROR_SUCCESS == RegQueryInfoKey(hkey, NULL, NULL, NULL, &cProfiles, &dwMax, NULL, NULL, NULL, NULL, NULL, NULL) && cProfiles > 0) { Assert(dwMax < MAX_PATH); cb = cProfiles * sizeof(MAPIACCTINFO); if (MemAlloc((void **)&m_rgInfo, cb)) { ZeroMemory(m_rgInfo, cb); for (i = 0; i < cProfiles; i++) { cb = sizeof(szProfile); lRet = RegEnumKeyEx(hkey, i, szProfile, &cb, NULL, NULL, NULL, NULL); if (lRet == ERROR_NO_MORE_ITEMS) break; else if (lRet != ERROR_SUCCESS) continue; if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szProfile, 0, KEY_ALL_ACCESS, &hkeyProfile)) { hkeyInet = InetMailProfile(hkeyProfile); if (hkeyInet != NULL) { m_rgInfo[m_cInfo].dwCookie = m_cInfo; m_rgInfo[m_cInfo].hkey = hkeyInet; StrCpyN(m_rgInfo[m_cInfo].szDisplay, szProfile, ARRAYSIZE(m_rgInfo[m_cInfo].szDisplay)); m_cInfo++; } RegCloseKey(hkeyProfile); } } } else { hr = E_OUTOFMEMORY; } } RegCloseKey(hkey); } if (0 == (dwFlags & ACCT_WIZ_OUTLOOK) && ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szInetAcctMgrRegKey, 0, KEY_READ, &hkey)) { cb = sizeof(szProfile); if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szRegOutlook, NULL, &type, (LPBYTE)szProfile, &cb)) { m_pAcctMan = new CAccountManager(); if (m_pAcctMan == NULL) { hr = E_OUTOFMEMORY; } else { hr = m_pAcctMan->InitEx(NULL, ACCT_INIT_OUTLOOK); if (SUCCEEDED(hr)) { if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_IMAP | SRV_POP3 | SRV_SMTP, &pEnumAccounts))) { if (SUCCEEDED(pEnumAccounts->GetCount(&i)) && i > 0) { cb = (m_cInfo + i) * sizeof(MAPIACCTINFO); if (MemRealloc((void **)&m_rgInfo, cb)) { ZeroMemory(&m_rgInfo[m_cInfo], i * sizeof(MAPIACCTINFO)); while (SUCCEEDED(pEnumAccounts->GetNext(&pAccount))) { if (SUCCEEDED(pAccount->GetPropSz(AP_ACCOUNT_NAME, m_rgInfo[m_cInfo].szDisplay, ARRAYSIZE(m_rgInfo[m_cInfo].szDisplay)))) { m_rgInfo[m_cInfo].dwCookie = m_cInfo; m_rgInfo[m_cInfo].pAccount = pAccount; pAccount->AddRef(); m_cInfo++; } pAccount->Release(); } } else { hr = E_OUTOFMEMORY; } } pEnumAccounts->Release(); } } } } RegCloseKey(hkey); } if (SUCCEEDED(hr)) { if (m_cInfo == 0) hr = S_FALSE; } *pcAcct = m_cInfo; return(hr); } HRESULT STDMETHODCALLTYPE CMAPIAcctImport::EnumerateAccounts(IEnumIMPACCOUNTS **ppEnum) { CEnumMAPIACCTS *penum; HRESULT hr; if (ppEnum == NULL) return(E_INVALIDARG); *ppEnum = NULL; if (m_cInfo == 0) return(S_FALSE); Assert(m_rgInfo != NULL); penum = new CEnumMAPIACCTS; if (penum == NULL) return(E_OUTOFMEMORY); hr = penum->Init(m_rgInfo, m_cInfo); if (FAILED(hr)) { penum->Release(); penum = NULL; } *ppEnum = penum; return(hr); } HRESULT STDMETHODCALLTYPE CMAPIAcctImport::GetSettings(DWORD_PTR dwCookie, IImnAccount *pAcct) { if (pAcct == NULL) return(E_INVALIDARG); return(IGetSettings(dwCookie, pAcct, NULL)); } HRESULT STDMETHODCALLTYPE CMAPIAcctImport::GetSettings2(DWORD_PTR dwCookie, IImnAccount *pAcct, IMPCONNINFO *pInfo) { if (pAcct == NULL || pInfo == NULL) return(E_INVALIDARG); return(IGetSettings(dwCookie, pAcct, pInfo)); } const static TCHAR c_szPopSvr[] = TEXT("001e6600"); const static TCHAR c_szAddr[] = TEXT("001e6605"); const static TCHAR c_szMAPIUsername[] = TEXT("001e6606"); const static TCHAR c_szName[] = TEXT("001e6607"); const static TCHAR c_szSmtpSvr[] = TEXT("001e6611"); typedef struct tagMAPISETTINGS { LPCTSTR sz; DWORD dwProp; } MAPISETTINGS; const static MAPISETTINGS c_rgSet[] = { {c_szPopSvr, AP_POP3_SERVER}, {c_szAddr, AP_SMTP_EMAIL_ADDRESS}, {c_szMAPIUsername, AP_POP3_USERNAME}, {c_szName, AP_SMTP_DISPLAY_NAME}, {c_szSmtpSvr, AP_SMTP_SERVER} }; #define CMAPISETTINGS ARRAYSIZE(c_rgSet) HRESULT STDMETHODCALLTYPE CMAPIAcctImport::IGetSettings(DWORD_PTR dwCookie, IImnAccount *pAcct, IMPCONNINFO *pInfo) { MAPIACCTINFO *pinfo; char sz[MAX_PATH]; DWORD cb, srv, dw; HRESULT hr; BOOL fIMAP; const MAPISETTINGS *pset; int i; LPCPROPINFO pProp; if (pAcct == NULL) return(E_INVALIDARG); Assert(((int) dwCookie) >= 0 && dwCookie < (DWORD_PTR)m_cInfo); pinfo = &m_rgInfo[dwCookie]; Assert(pinfo->dwCookie == dwCookie); hr = pAcct->SetPropSz(AP_ACCOUNT_NAME, pinfo->szDisplay); if (FAILED(hr)) return(hr); if (pinfo->hkey != NULL) { for (i = 0, pset = c_rgSet; i < CMAPISETTINGS; i++, pset++) { cb = sizeof(sz); if (ERROR_SUCCESS == RegQueryValueEx(pinfo->hkey, pset->sz, NULL, NULL, (LPBYTE)sz, &cb) && !FIsEmpty(sz)) { pAcct->SetPropSz(pset->dwProp, sz); // in exchange if no SMTP server is specified, then the SMTP server // is the same as the POP3 server // ASSUMPTION: pop server MUST come before smtp server in c_rgSet if (pset->dwProp == AP_POP3_SERVER) pAcct->SetPropSz(AP_SMTP_SERVER, sz); } } } else { Assert(pinfo->pAccount != NULL); hr = pinfo->pAccount->GetServerTypes(&srv); if (SUCCEEDED(hr) && !!(srv & (SRV_POP3 | SRV_IMAP))) { fIMAP = (srv & SRV_IMAP); for (i = 0, pProp = g_rgAcctPropSet; i < NUM_ACCT_PROPS; i++, pProp++) { if ((fIMAP && pProp->dwPropTag >= AP_IMAP_FIRST && pProp->dwPropTag <= AP_IMAP_LAST) || (!fIMAP && pProp->dwPropTag >= AP_POP3_FIRST && pProp->dwPropTag <= AP_POP3_LAST) || (pProp->dwPropTag >= AP_SMTP_FIRST && pProp->dwPropTag <= AP_SMTP_LAST)) { cb = sizeof(sz); hr = pinfo->pAccount->GetProp(pProp->dwPropTag, (LPBYTE)sz, &cb); if (hr == S_OK) pAcct->SetProp(pProp->dwPropTag, (LPBYTE)sz, cb); } } if (pInfo != NULL) { hr = pinfo->pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dw); if (hr == S_OK) { if (dw == CONNECTION_TYPE_RAS) { cb = sizeof(sz); hr = pinfo->pAccount->GetProp(AP_RAS_CONNECTOID, (LPBYTE)sz, &cb); if (SUCCEEDED(hr)) { StrCpyN(pInfo->szConnectoid, sz, ARRAYSIZE(pInfo->szConnectoid)); pInfo->dwConnect = CONN_USE_SETTINGS; pInfo->dwConnectType = dw; } } else { pInfo->dwConnect = CONN_USE_SETTINGS; pInfo->dwConnectType = dw; } } } } } return(S_OK); } CEnumMAPIACCTS::CEnumMAPIACCTS() { m_cRef = 1; // m_iInfo m_cInfo = 0; m_rgInfo = NULL; } CEnumMAPIACCTS::~CEnumMAPIACCTS() { if (m_rgInfo != NULL) MemFree(m_rgInfo); } STDMETHODIMP CEnumMAPIACCTS::QueryInterface(REFIID riid, LPVOID *ppv) { if (ppv == NULL) return(E_INVALIDARG); *ppv = NULL; if (IID_IUnknown == riid) *ppv = (IUnknown *)this; else if (IID_IEnumIMPACCOUNTS == riid) *ppv = (IEnumIMPACCOUNTS *)this; if (*ppv != NULL) ((LPUNKNOWN)*ppv)->AddRef(); else return(E_NOINTERFACE); return(S_OK); } STDMETHODIMP_(ULONG) CEnumMAPIACCTS::AddRef() { return(++m_cRef); } STDMETHODIMP_(ULONG) CEnumMAPIACCTS::Release() { if (--m_cRef == 0) { delete this; return(0); } return(m_cRef); } HRESULT STDMETHODCALLTYPE CEnumMAPIACCTS::Next(IMPACCOUNTINFO *pinfo) { if (pinfo == NULL) return(E_INVALIDARG); m_iInfo++; if ((UINT)m_iInfo >= m_cInfo) return(S_FALSE); Assert(m_rgInfo != NULL); pinfo->dwCookie = m_rgInfo[m_iInfo].dwCookie; pinfo->dwReserved = 0; StrCpyN(pinfo->szDisplay, m_rgInfo[m_iInfo].szDisplay, ARRAYSIZE(pinfo->szDisplay)); return(S_OK); } HRESULT STDMETHODCALLTYPE CEnumMAPIACCTS::Reset() { m_iInfo = -1; return(S_OK); } HRESULT CEnumMAPIACCTS::Init(MAPIACCTINFO *pinfo, int cinfo) { DWORD cb; Assert(pinfo != NULL); Assert(cinfo > 0); cb = cinfo * sizeof(MAPIACCTINFO); if (!MemAlloc((void **)&m_rgInfo, cb)) return(E_OUTOFMEMORY); m_iInfo = -1; m_cInfo = cinfo; CopyMemory(m_rgInfo, pinfo, cb); return(S_OK); } BOOL MatchingPrefix(LPCTSTR sz, LPCTSTR szPrefix) { Assert(sz != NULL); Assert(szPrefix != NULL); while (*szPrefix != 0) { if (*sz == 0 || *sz != *szPrefix) return(FALSE); szPrefix++; sz++; } return(TRUE); } void SzFromBinary(BYTE *pb, TCHAR *sz, int cb) { int i; Assert(pb != NULL); Assert(sz != NULL); for (i = 0; i < cb; i++) { wnsprintf(sz, (cb / sizeof(sz[0])), TEXT("%0.2x"), *pb); pb++; sz += 2; } *sz = 0; } #define CBTURD 16 const static TCHAR c_sz9207[] = TEXT("9207"); const static TCHAR c_szBullshit[] = TEXT("01023d02"); const static TCHAR c_szImailValue[] = TEXT("001e3d09"); const static TCHAR c_szGarbage[] = TEXT("01023d0c"); const static TCHAR c_szImail[] = TEXT("IMAIL"); const static TCHAR c_szImep[] = TEXT("001e661f"); HKEY InetMailProfile(HKEY hkey) { HKEY hkeyInet, hkey9207, hkeyTurd; TCHAR szKey[MAX_PATH], szTurd[CBTURD * 2 + 1]; BYTE *pb, *pbT, rgbGarbage[CBTURD]; LONG lRet; DWORD cb, i, iTurd, cTurds, iByte; hkeyInet = NULL; i = 0; while (hkeyInet == NULL) { cb = sizeof(szKey); lRet = RegEnumKeyEx(hkey, i++, szKey, &cb, NULL, NULL, NULL, NULL); if (lRet == ERROR_NO_MORE_ITEMS) break; else if (lRet != ERROR_SUCCESS) continue; if (!MatchingPrefix(szKey, c_sz9207)) continue; if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szKey, 0, KEY_ALL_ACCESS, &hkey9207)) { if (ERROR_SUCCESS == RegQueryValueEx(hkey9207, c_szBullshit, NULL, NULL, NULL, &cb) && cb > 0) { if (MemAlloc((void **)&pb, cb)) { if (ERROR_SUCCESS == RegQueryValueEx(hkey9207, c_szBullshit, NULL, NULL, pb, &cb)) { cTurds = cb / CBTURD; pbT = pb; for (iTurd = 0; iTurd < cTurds && hkeyInet == NULL; iTurd++) { SzFromBinary(pbT, szTurd, CBTURD); pbT += CBTURD; if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szTurd, 0, KEY_ALL_ACCESS, &hkeyTurd)) { cb = sizeof(szKey); if (ERROR_SUCCESS == RegQueryValueEx(hkeyTurd, c_szImailValue, NULL, NULL, (LPBYTE)szKey, &cb) && 0 == lstrcmpi(szKey, c_szImail)) { cb = sizeof(rgbGarbage); if (ERROR_SUCCESS == RegQueryValueEx(hkeyTurd, c_szGarbage, NULL, NULL, rgbGarbage, &cb)) { Assert(cb == CBTURD); SzFromBinary(rgbGarbage, szTurd, CBTURD); if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szTurd, 0, KEY_ALL_ACCESS, &hkeyInet)) { if (ERROR_SUCCESS == RegQueryValueEx(hkeyInet, c_szImep, NULL, NULL, NULL, &cb)) { RegCloseKey(hkeyInet); hkeyInet = NULL; } } } } RegCloseKey(hkeyTurd); } } } MemFree(pb); } } RegCloseKey(hkey9207); } } return(hkeyInet); } HRESULT STDMETHODCALLTYPE CMAPIAcctImport::InitializeImport(HWND hwnd, DWORD_PTR dwCookie) { return(E_NOTIMPL); } HRESULT STDMETHODCALLTYPE CMAPIAcctImport::GetNewsGroup(INewsGroupImport *pImp, DWORD dwReserved) { return(E_NOTIMPL); }