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.

602 lines
17 KiB

  1. #include "pch.hxx"
  2. #include <imnact.h>
  3. #include <acctimp.h>
  4. #include <dllmain.h>
  5. #include <resource.h>
  6. #include "exchacct.h"
  7. #include "acctman.h"
  8. #include "strconst.h"
  9. #include "demand.h"
  10. ASSERTDATA
  11. HKEY InetMailProfile(HKEY hkey);
  12. CMAPIAcctImport::CMAPIAcctImport()
  13. {
  14. m_cRef = 1;
  15. m_cInfo = 0;
  16. m_rgInfo = NULL;
  17. m_pAcctMan = NULL;
  18. }
  19. CMAPIAcctImport::~CMAPIAcctImport()
  20. {
  21. UINT i;
  22. if (m_rgInfo != NULL)
  23. {
  24. for (i = 0; i < m_cInfo; i++)
  25. {
  26. if (m_rgInfo[i].hkey != NULL)
  27. RegCloseKey(m_rgInfo[i].hkey);
  28. if (m_rgInfo[i].pAccount != NULL)
  29. m_rgInfo[i].pAccount->Release();
  30. }
  31. MemFree(m_rgInfo);
  32. }
  33. if (m_pAcctMan != NULL)
  34. m_pAcctMan->Release();
  35. }
  36. STDMETHODIMP CMAPIAcctImport::QueryInterface(REFIID riid, LPVOID *ppv)
  37. {
  38. if (ppv == NULL)
  39. return(E_INVALIDARG);
  40. *ppv = NULL;
  41. if (IID_IUnknown == riid)
  42. *ppv = (IAccountImport *)this;
  43. else if (IID_IAccountImport == riid)
  44. *ppv = (IAccountImport *)this;
  45. else if (IID_IAccountImport2 == riid)
  46. *ppv = (IAccountImport2 *)this;
  47. else
  48. return(E_NOINTERFACE);
  49. ((LPUNKNOWN)*ppv)->AddRef();
  50. return(S_OK);
  51. }
  52. STDMETHODIMP_(ULONG) CMAPIAcctImport::AddRef()
  53. {
  54. return(++m_cRef);
  55. }
  56. STDMETHODIMP_(ULONG) CMAPIAcctImport::Release()
  57. {
  58. if (--m_cRef == 0)
  59. {
  60. delete this;
  61. return(0);
  62. }
  63. return(m_cRef);
  64. }
  65. const static char c_szRegNT[] = "Software\\Microsoft\\Windows NT\\CurrentVersion\\Windows Messaging Subsystem\\Profiles";
  66. const static char c_szRegWin[] = "Software\\Microsoft\\Windows Messaging Subsystem\\Profiles";
  67. HRESULT STDMETHODCALLTYPE CMAPIAcctImport::AutoDetect(DWORD *pcAcct, DWORD dwFlags)
  68. {
  69. LONG lRet;
  70. TCHAR szProfile[MAX_PATH];
  71. HKEY hkey, hkeyProfile, hkeyInet;
  72. HRESULT hr;
  73. DWORD i, type, cb, cProfiles, dwMax;
  74. OSVERSIONINFO osinfo;
  75. BOOL fNT;
  76. IImnEnumAccounts *pEnumAccounts;
  77. IImnAccount *pAccount;
  78. if (pcAcct == NULL)
  79. return(E_INVALIDARG);
  80. hr = S_OK;
  81. *pcAcct = 0;
  82. cProfiles = 0;
  83. osinfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
  84. GetVersionEx(&osinfo);
  85. fNT = (osinfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
  86. if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_CURRENT_USER, fNT ? c_szRegNT : c_szRegWin, 0, KEY_ALL_ACCESS, &hkey))
  87. {
  88. if (ERROR_SUCCESS == RegQueryInfoKey(hkey, NULL, NULL, NULL, &cProfiles, &dwMax, NULL, NULL, NULL, NULL, NULL, NULL) &&
  89. cProfiles > 0)
  90. {
  91. Assert(dwMax < MAX_PATH);
  92. cb = cProfiles * sizeof(MAPIACCTINFO);
  93. if (MemAlloc((void **)&m_rgInfo, cb))
  94. {
  95. ZeroMemory(m_rgInfo, cb);
  96. for (i = 0; i < cProfiles; i++)
  97. {
  98. cb = sizeof(szProfile);
  99. lRet = RegEnumKeyEx(hkey, i, szProfile, &cb, NULL, NULL, NULL, NULL);
  100. if (lRet == ERROR_NO_MORE_ITEMS)
  101. break;
  102. else if (lRet != ERROR_SUCCESS)
  103. continue;
  104. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szProfile, 0, KEY_ALL_ACCESS, &hkeyProfile))
  105. {
  106. hkeyInet = InetMailProfile(hkeyProfile);
  107. if (hkeyInet != NULL)
  108. {
  109. m_rgInfo[m_cInfo].dwCookie = m_cInfo;
  110. m_rgInfo[m_cInfo].hkey = hkeyInet;
  111. StrCpyN(m_rgInfo[m_cInfo].szDisplay, szProfile, ARRAYSIZE(m_rgInfo[m_cInfo].szDisplay));
  112. m_cInfo++;
  113. }
  114. RegCloseKey(hkeyProfile);
  115. }
  116. }
  117. }
  118. else
  119. {
  120. hr = E_OUTOFMEMORY;
  121. }
  122. }
  123. RegCloseKey(hkey);
  124. }
  125. if (0 == (dwFlags & ACCT_WIZ_OUTLOOK) &&
  126. ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szInetAcctMgrRegKey, 0, KEY_READ, &hkey))
  127. {
  128. cb = sizeof(szProfile);
  129. if (ERROR_SUCCESS == RegQueryValueEx(hkey, c_szRegOutlook, NULL, &type, (LPBYTE)szProfile, &cb))
  130. {
  131. m_pAcctMan = new CAccountManager();
  132. if (m_pAcctMan == NULL)
  133. {
  134. hr = E_OUTOFMEMORY;
  135. }
  136. else
  137. {
  138. hr = m_pAcctMan->InitEx(NULL, ACCT_INIT_OUTLOOK);
  139. if (SUCCEEDED(hr))
  140. {
  141. if (SUCCEEDED(m_pAcctMan->Enumerate(SRV_IMAP | SRV_POP3 | SRV_SMTP, &pEnumAccounts)))
  142. {
  143. if (SUCCEEDED(pEnumAccounts->GetCount(&i)) && i > 0)
  144. {
  145. cb = (m_cInfo + i) * sizeof(MAPIACCTINFO);
  146. if (MemRealloc((void **)&m_rgInfo, cb))
  147. {
  148. ZeroMemory(&m_rgInfo[m_cInfo], i * sizeof(MAPIACCTINFO));
  149. while (SUCCEEDED(pEnumAccounts->GetNext(&pAccount)))
  150. {
  151. if (SUCCEEDED(pAccount->GetPropSz(AP_ACCOUNT_NAME, m_rgInfo[m_cInfo].szDisplay, ARRAYSIZE(m_rgInfo[m_cInfo].szDisplay))))
  152. {
  153. m_rgInfo[m_cInfo].dwCookie = m_cInfo;
  154. m_rgInfo[m_cInfo].pAccount = pAccount;
  155. pAccount->AddRef();
  156. m_cInfo++;
  157. }
  158. pAccount->Release();
  159. }
  160. }
  161. else
  162. {
  163. hr = E_OUTOFMEMORY;
  164. }
  165. }
  166. pEnumAccounts->Release();
  167. }
  168. }
  169. }
  170. }
  171. RegCloseKey(hkey);
  172. }
  173. if (SUCCEEDED(hr))
  174. {
  175. if (m_cInfo == 0)
  176. hr = S_FALSE;
  177. }
  178. *pcAcct = m_cInfo;
  179. return(hr);
  180. }
  181. HRESULT STDMETHODCALLTYPE CMAPIAcctImport::EnumerateAccounts(IEnumIMPACCOUNTS **ppEnum)
  182. {
  183. CEnumMAPIACCTS *penum;
  184. HRESULT hr;
  185. if (ppEnum == NULL)
  186. return(E_INVALIDARG);
  187. *ppEnum = NULL;
  188. if (m_cInfo == 0)
  189. return(S_FALSE);
  190. Assert(m_rgInfo != NULL);
  191. penum = new CEnumMAPIACCTS;
  192. if (penum == NULL)
  193. return(E_OUTOFMEMORY);
  194. hr = penum->Init(m_rgInfo, m_cInfo);
  195. if (FAILED(hr))
  196. {
  197. penum->Release();
  198. penum = NULL;
  199. }
  200. *ppEnum = penum;
  201. return(hr);
  202. }
  203. HRESULT STDMETHODCALLTYPE CMAPIAcctImport::GetSettings(DWORD_PTR dwCookie, IImnAccount *pAcct)
  204. {
  205. if (pAcct == NULL)
  206. return(E_INVALIDARG);
  207. return(IGetSettings(dwCookie, pAcct, NULL));
  208. }
  209. HRESULT STDMETHODCALLTYPE CMAPIAcctImport::GetSettings2(DWORD_PTR dwCookie, IImnAccount *pAcct, IMPCONNINFO *pInfo)
  210. {
  211. if (pAcct == NULL ||
  212. pInfo == NULL)
  213. return(E_INVALIDARG);
  214. return(IGetSettings(dwCookie, pAcct, pInfo));
  215. }
  216. const static TCHAR c_szPopSvr[] = TEXT("001e6600");
  217. const static TCHAR c_szAddr[] = TEXT("001e6605");
  218. const static TCHAR c_szMAPIUsername[] = TEXT("001e6606");
  219. const static TCHAR c_szName[] = TEXT("001e6607");
  220. const static TCHAR c_szSmtpSvr[] = TEXT("001e6611");
  221. typedef struct tagMAPISETTINGS
  222. {
  223. LPCTSTR sz;
  224. DWORD dwProp;
  225. } MAPISETTINGS;
  226. const static MAPISETTINGS c_rgSet[] =
  227. {
  228. {c_szPopSvr, AP_POP3_SERVER},
  229. {c_szAddr, AP_SMTP_EMAIL_ADDRESS},
  230. {c_szMAPIUsername, AP_POP3_USERNAME},
  231. {c_szName, AP_SMTP_DISPLAY_NAME},
  232. {c_szSmtpSvr, AP_SMTP_SERVER}
  233. };
  234. #define CMAPISETTINGS ARRAYSIZE(c_rgSet)
  235. HRESULT STDMETHODCALLTYPE CMAPIAcctImport::IGetSettings(DWORD_PTR dwCookie, IImnAccount *pAcct, IMPCONNINFO *pInfo)
  236. {
  237. MAPIACCTINFO *pinfo;
  238. char sz[MAX_PATH];
  239. DWORD cb, srv, dw;
  240. HRESULT hr;
  241. BOOL fIMAP;
  242. const MAPISETTINGS *pset;
  243. int i;
  244. LPCPROPINFO pProp;
  245. if (pAcct == NULL)
  246. return(E_INVALIDARG);
  247. Assert(((int) dwCookie) >= 0 && dwCookie < (DWORD_PTR)m_cInfo);
  248. pinfo = &m_rgInfo[dwCookie];
  249. Assert(pinfo->dwCookie == dwCookie);
  250. hr = pAcct->SetPropSz(AP_ACCOUNT_NAME, pinfo->szDisplay);
  251. if (FAILED(hr))
  252. return(hr);
  253. if (pinfo->hkey != NULL)
  254. {
  255. for (i = 0, pset = c_rgSet; i < CMAPISETTINGS; i++, pset++)
  256. {
  257. cb = sizeof(sz);
  258. if (ERROR_SUCCESS == RegQueryValueEx(pinfo->hkey, pset->sz, NULL, NULL, (LPBYTE)sz, &cb) &&
  259. !FIsEmpty(sz))
  260. {
  261. pAcct->SetPropSz(pset->dwProp, sz);
  262. // in exchange if no SMTP server is specified, then the SMTP server
  263. // is the same as the POP3 server
  264. // ASSUMPTION: pop server MUST come before smtp server in c_rgSet
  265. if (pset->dwProp == AP_POP3_SERVER)
  266. pAcct->SetPropSz(AP_SMTP_SERVER, sz);
  267. }
  268. }
  269. }
  270. else
  271. {
  272. Assert(pinfo->pAccount != NULL);
  273. hr = pinfo->pAccount->GetServerTypes(&srv);
  274. if (SUCCEEDED(hr) && !!(srv & (SRV_POP3 | SRV_IMAP)))
  275. {
  276. fIMAP = (srv & SRV_IMAP);
  277. for (i = 0, pProp = g_rgAcctPropSet; i < NUM_ACCT_PROPS; i++, pProp++)
  278. {
  279. if ((fIMAP && pProp->dwPropTag >= AP_IMAP_FIRST && pProp->dwPropTag <= AP_IMAP_LAST) ||
  280. (!fIMAP && pProp->dwPropTag >= AP_POP3_FIRST && pProp->dwPropTag <= AP_POP3_LAST) ||
  281. (pProp->dwPropTag >= AP_SMTP_FIRST && pProp->dwPropTag <= AP_SMTP_LAST))
  282. {
  283. cb = sizeof(sz);
  284. hr = pinfo->pAccount->GetProp(pProp->dwPropTag, (LPBYTE)sz, &cb);
  285. if (hr == S_OK)
  286. pAcct->SetProp(pProp->dwPropTag, (LPBYTE)sz, cb);
  287. }
  288. }
  289. if (pInfo != NULL)
  290. {
  291. hr = pinfo->pAccount->GetPropDw(AP_RAS_CONNECTION_TYPE, &dw);
  292. if (hr == S_OK)
  293. {
  294. if (dw == CONNECTION_TYPE_RAS)
  295. {
  296. cb = sizeof(sz);
  297. hr = pinfo->pAccount->GetProp(AP_RAS_CONNECTOID, (LPBYTE)sz, &cb);
  298. if (SUCCEEDED(hr))
  299. {
  300. StrCpyN(pInfo->szConnectoid, sz, ARRAYSIZE(pInfo->szConnectoid));
  301. pInfo->dwConnect = CONN_USE_SETTINGS;
  302. pInfo->dwConnectType = dw;
  303. }
  304. }
  305. else
  306. {
  307. pInfo->dwConnect = CONN_USE_SETTINGS;
  308. pInfo->dwConnectType = dw;
  309. }
  310. }
  311. }
  312. }
  313. }
  314. return(S_OK);
  315. }
  316. CEnumMAPIACCTS::CEnumMAPIACCTS()
  317. {
  318. m_cRef = 1;
  319. // m_iInfo
  320. m_cInfo = 0;
  321. m_rgInfo = NULL;
  322. }
  323. CEnumMAPIACCTS::~CEnumMAPIACCTS()
  324. {
  325. if (m_rgInfo != NULL)
  326. MemFree(m_rgInfo);
  327. }
  328. STDMETHODIMP CEnumMAPIACCTS::QueryInterface(REFIID riid, LPVOID *ppv)
  329. {
  330. if (ppv == NULL)
  331. return(E_INVALIDARG);
  332. *ppv = NULL;
  333. if (IID_IUnknown == riid)
  334. *ppv = (IUnknown *)this;
  335. else if (IID_IEnumIMPACCOUNTS == riid)
  336. *ppv = (IEnumIMPACCOUNTS *)this;
  337. if (*ppv != NULL)
  338. ((LPUNKNOWN)*ppv)->AddRef();
  339. else
  340. return(E_NOINTERFACE);
  341. return(S_OK);
  342. }
  343. STDMETHODIMP_(ULONG) CEnumMAPIACCTS::AddRef()
  344. {
  345. return(++m_cRef);
  346. }
  347. STDMETHODIMP_(ULONG) CEnumMAPIACCTS::Release()
  348. {
  349. if (--m_cRef == 0)
  350. {
  351. delete this;
  352. return(0);
  353. }
  354. return(m_cRef);
  355. }
  356. HRESULT STDMETHODCALLTYPE CEnumMAPIACCTS::Next(IMPACCOUNTINFO *pinfo)
  357. {
  358. if (pinfo == NULL)
  359. return(E_INVALIDARG);
  360. m_iInfo++;
  361. if ((UINT)m_iInfo >= m_cInfo)
  362. return(S_FALSE);
  363. Assert(m_rgInfo != NULL);
  364. pinfo->dwCookie = m_rgInfo[m_iInfo].dwCookie;
  365. pinfo->dwReserved = 0;
  366. StrCpyN(pinfo->szDisplay, m_rgInfo[m_iInfo].szDisplay, ARRAYSIZE(pinfo->szDisplay));
  367. return(S_OK);
  368. }
  369. HRESULT STDMETHODCALLTYPE CEnumMAPIACCTS::Reset()
  370. {
  371. m_iInfo = -1;
  372. return(S_OK);
  373. }
  374. HRESULT CEnumMAPIACCTS::Init(MAPIACCTINFO *pinfo, int cinfo)
  375. {
  376. DWORD cb;
  377. Assert(pinfo != NULL);
  378. Assert(cinfo > 0);
  379. cb = cinfo * sizeof(MAPIACCTINFO);
  380. if (!MemAlloc((void **)&m_rgInfo, cb))
  381. return(E_OUTOFMEMORY);
  382. m_iInfo = -1;
  383. m_cInfo = cinfo;
  384. CopyMemory(m_rgInfo, pinfo, cb);
  385. return(S_OK);
  386. }
  387. BOOL MatchingPrefix(LPCTSTR sz, LPCTSTR szPrefix)
  388. {
  389. Assert(sz != NULL);
  390. Assert(szPrefix != NULL);
  391. while (*szPrefix != 0)
  392. {
  393. if (*sz == 0 ||
  394. *sz != *szPrefix)
  395. return(FALSE);
  396. szPrefix++;
  397. sz++;
  398. }
  399. return(TRUE);
  400. }
  401. void SzFromBinary(BYTE *pb, TCHAR *sz, int cb)
  402. {
  403. int i;
  404. Assert(pb != NULL);
  405. Assert(sz != NULL);
  406. for (i = 0; i < cb; i++)
  407. {
  408. wnsprintf(sz, (cb / sizeof(sz[0])), TEXT("%0.2x"), *pb);
  409. pb++;
  410. sz += 2;
  411. }
  412. *sz = 0;
  413. }
  414. #define CBTURD 16
  415. const static TCHAR c_sz9207[] = TEXT("9207");
  416. const static TCHAR c_szBullshit[] = TEXT("01023d02");
  417. const static TCHAR c_szImailValue[] = TEXT("001e3d09");
  418. const static TCHAR c_szGarbage[] = TEXT("01023d0c");
  419. const static TCHAR c_szImail[] = TEXT("IMAIL");
  420. const static TCHAR c_szImep[] = TEXT("001e661f");
  421. HKEY InetMailProfile(HKEY hkey)
  422. {
  423. HKEY hkeyInet, hkey9207, hkeyTurd;
  424. TCHAR szKey[MAX_PATH], szTurd[CBTURD * 2 + 1];
  425. BYTE *pb, *pbT, rgbGarbage[CBTURD];
  426. LONG lRet;
  427. DWORD cb, i, iTurd, cTurds, iByte;
  428. hkeyInet = NULL;
  429. i = 0;
  430. while (hkeyInet == NULL)
  431. {
  432. cb = sizeof(szKey);
  433. lRet = RegEnumKeyEx(hkey, i++, szKey, &cb, NULL, NULL, NULL, NULL);
  434. if (lRet == ERROR_NO_MORE_ITEMS)
  435. break;
  436. else if (lRet != ERROR_SUCCESS)
  437. continue;
  438. if (!MatchingPrefix(szKey, c_sz9207))
  439. continue;
  440. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szKey, 0, KEY_ALL_ACCESS, &hkey9207))
  441. {
  442. if (ERROR_SUCCESS == RegQueryValueEx(hkey9207, c_szBullshit, NULL, NULL, NULL, &cb) && cb > 0)
  443. {
  444. if (MemAlloc((void **)&pb, cb))
  445. {
  446. if (ERROR_SUCCESS == RegQueryValueEx(hkey9207, c_szBullshit, NULL, NULL, pb, &cb))
  447. {
  448. cTurds = cb / CBTURD;
  449. pbT = pb;
  450. for (iTurd = 0; iTurd < cTurds && hkeyInet == NULL; iTurd++)
  451. {
  452. SzFromBinary(pbT, szTurd, CBTURD);
  453. pbT += CBTURD;
  454. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szTurd, 0, KEY_ALL_ACCESS, &hkeyTurd))
  455. {
  456. cb = sizeof(szKey);
  457. if (ERROR_SUCCESS == RegQueryValueEx(hkeyTurd, c_szImailValue, NULL, NULL, (LPBYTE)szKey, &cb) &&
  458. 0 == lstrcmpi(szKey, c_szImail))
  459. {
  460. cb = sizeof(rgbGarbage);
  461. if (ERROR_SUCCESS == RegQueryValueEx(hkeyTurd, c_szGarbage, NULL, NULL, rgbGarbage, &cb))
  462. {
  463. Assert(cb == CBTURD);
  464. SzFromBinary(rgbGarbage, szTurd, CBTURD);
  465. if (ERROR_SUCCESS == RegOpenKeyEx(hkey, szTurd, 0, KEY_ALL_ACCESS, &hkeyInet))
  466. {
  467. if (ERROR_SUCCESS == RegQueryValueEx(hkeyInet, c_szImep, NULL, NULL, NULL, &cb))
  468. {
  469. RegCloseKey(hkeyInet);
  470. hkeyInet = NULL;
  471. }
  472. }
  473. }
  474. }
  475. RegCloseKey(hkeyTurd);
  476. }
  477. }
  478. }
  479. MemFree(pb);
  480. }
  481. }
  482. RegCloseKey(hkey9207);
  483. }
  484. }
  485. return(hkeyInet);
  486. }
  487. HRESULT STDMETHODCALLTYPE CMAPIAcctImport::InitializeImport(HWND hwnd, DWORD_PTR dwCookie)
  488. {
  489. return(E_NOTIMPL);
  490. }
  491. HRESULT STDMETHODCALLTYPE CMAPIAcctImport::GetNewsGroup(INewsGroupImport *pImp, DWORD dwReserved)
  492. {
  493. return(E_NOTIMPL);
  494. }