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.

607 lines
19 KiB

  1. //
  2. // DLL.CPP - Dll initialization routines
  3. //
  4. #include "pch.hxx"
  5. #include "strconst.h"
  6. #include <shlguid.h>
  7. #include "ourguid.h"
  8. #include "globals.h"
  9. #include "folder.h"
  10. #include "newsview.h"
  11. #include "mimeole.h"
  12. #include "mimeutil.h"
  13. #include "mailnote.h"
  14. #include "newsnote.h"
  15. #include "resource.h"
  16. #include "init.h"
  17. #include <store.h>
  18. #include "url.h"
  19. #include "shelutil.h"
  20. #include <goptions.h>
  21. #include "nnserver.h"
  22. #include "storfldr.h" // IsThisNashville
  23. #include "strconst.h"
  24. #include "grplist.h"
  25. #include "shlwapi.h"
  26. #include "shlwapip.h"
  27. #include <secutil.h>
  28. #include <error.h>
  29. #ifndef WIN16 //RUN16_MSLU
  30. #include <msluapi.h>
  31. #include <msluguid.h>
  32. #endif //!WIN16
  33. extern HRESULT BrowseToObject(LPCITEMIDLIST pidl);
  34. HRESULT HrOpenMessage(HFOLDER hfldr, MSGID msgid, LPMIMEMESSAGE *ppMsg);
  35. BOOL ParseFolderMsgId(LPSTR pszCmdLine, HFOLDER *phfldr, MSGID *pmsgid);
  36. HRESULT HrDownloadArticleDialog(CNNTPServer *pNNTPServer, LPTSTR pszArticle, LPMIMEMESSAGE *ppMsg);
  37. ///////////////////////////////////////////////////////////////////////
  38. //
  39. // FUNCTION: HandleNWSFile
  40. //
  41. // PURPOSE: Provides an entry point into Thor that allows us to be
  42. // invoked from a URL. The pszCmdLine paramter must be a
  43. // valid News URL or nothing happens.
  44. //
  45. ///////////////////////////////////////////////////////////////////////
  46. HRESULT HandleNWSFile(LPTSTR pszCmd)
  47. {
  48. #ifndef WIN16 //RUN16_NEWS
  49. LPMIMEMESSAGE pMsg;
  50. int idsErr = idsNewsRundllFailed;
  51. NCINFO nci = { 0 };
  52. if (!pszCmd|| !*pszCmd)
  53. goto exit;
  54. DOUTL(1, TEXT("HandleNWSFile - pszCmd = %s"), pszCmd);
  55. if ((UINT)GetFileAttributes (pszCmd) == (UINT)-1)
  56. {
  57. idsErr = idsErrNewsCantOpen;
  58. goto exit;
  59. }
  60. // Do the basic DLL initialization first.
  61. if (!Initialize_RunDLL(FALSE))
  62. goto exit;
  63. // Create new message
  64. if (SUCCEEDED(HrCreateMessage(&pMsg)))
  65. {
  66. if (SUCCEEDED(HrLoadMsgFromFile(pMsg, pszCmd)))
  67. {
  68. LPSTR lpszUnsent;
  69. nci.ntNote = ntReadNote;
  70. nci.dwFlags = NCF_NEWS;
  71. nci.pMsg = pMsg;
  72. if (MimeOleGetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_XUNSENT), NOFLAGS, &lpszUnsent) == S_OK)
  73. {
  74. if (*lpszUnsent)
  75. nci.ntNote = ntSendNote;
  76. SafeMimeOleFree(lpszUnsent);
  77. }
  78. if (SUCCEEDED(HrCreateNote(&nci)))
  79. idsErr = 0;
  80. }
  81. else
  82. idsErr = idsErrNewsCantOpen;
  83. pMsg->Release();
  84. }
  85. Uninitialize_RunDLL();
  86. exit:
  87. if (idsErr)
  88. AthMessageBoxW(GetDesktopWindow(),
  89. MAKEINTRESOURCEW(idsAthenaNews),
  90. MAKEINTRESOURCEW(idsErr),
  91. 0,
  92. MB_ICONEXCLAMATION | MB_OK);
  93. return (idsErr) ? E_FAIL : S_OK;
  94. #else
  95. return( E_NOTIMPL );
  96. #endif //!WIN16
  97. }
  98. ///////////////////////////////////////////////////////////////////////
  99. //
  100. // FUNCTION: HandleNewsArticleURL
  101. //
  102. // PURPOSE: Provides an entry point into Thor that allows us to be
  103. // invoked from a URL. The pszCmdLine paramter must be a
  104. // valid News URL or nothing happens.
  105. //
  106. ///////////////////////////////////////////////////////////////////////
  107. HRESULT HandleNewsArticleURL(LPTSTR pszServerIn, LPTSTR pszArticle, UINT uPort, BOOL fSecure)
  108. {
  109. #ifndef WIN16 //RUN16_NEWS
  110. NCINFO nci;
  111. CNNTPServer *pNNTPServer = NULL;
  112. HRESULT hr = E_FAIL;
  113. TCHAR szAccount[CCHMAX_ACCOUNT_NAME];
  114. TCHAR szArticleId[1024];
  115. IImnAccount *pAcct = NULL;
  116. LPMIMEMESSAGE pMsg = NULL;
  117. // The URL specified an article id. In this case we ONLY want to
  118. // display a ReadNote window. This requires a bit of work.
  119. // Do the basic DLL initialization first.
  120. if (!Initialize_RunDLL(FALSE))
  121. {
  122. AthMessageBoxW(GetDesktopWindow(),
  123. MAKEINTRESOURCEW(idsAthenaNews),
  124. MAKEINTRESOURCEW(idsNewsRundllFailed),
  125. 0,
  126. MB_ICONEXCLAMATION | MB_OK);
  127. return E_FAIL;
  128. }
  129. // If a server was specified, then try to create a temp account for it
  130. if (pszServerIn &&
  131. *pszServerIn &&
  132. SUCCEEDED(NewsUtil_CreateTempAccount(pszServerIn, uPort, fSecure, &pAcct)))
  133. {
  134. pAcct->GetPropSz(AP_ACCOUNT_NAME, szAccount, ARRAYSIZE(szAccount));
  135. pAcct->Release();
  136. }
  137. else
  138. {
  139. // If a server wasn't specified, then use the default account
  140. if (NewsUtil_GetDefaultServer(szAccount, ARRAYSIZE(szAccount)) != S_OK)
  141. goto exit;
  142. }
  143. // Need to invoke read note. First create and initialize an server.
  144. pNNTPServer = new CNNTPServer();
  145. if (!pNNTPServer)
  146. goto exit;
  147. if (FAILED(pNNTPServer->HrInit(szAccount)))
  148. goto exit;
  149. if (FAILED(pNNTPServer->Connect()))
  150. goto exit;
  151. // Bug #10555 - The URL shouldn't have <> around the article ID, but some
  152. // lameoids probably will do it anyway, so deal with it.
  153. StrCpyN(szArticleId, pszArticle, ARRAYSIZE(szArticleId));
  154. if (!IsDBCSLeadByte(*pszArticle))
  155. {
  156. if (*pszArticle != '<')
  157. wnsprintf(szArticleId, ARRAYSIZE(szArticleId), TEXT("<%s>"), pszArticle);
  158. }
  159. if (SUCCEEDED(hr = HrDownloadArticleDialog(pNNTPServer, szArticleId, &pMsg)))
  160. {
  161. // Initialize the NNCI struct so we can invoke a note window.
  162. ZeroMemory(&nci, sizeof(NCINFO));
  163. nci.ntNote = ntReadNote;
  164. nci.dwFlags = NCF_NEWS;
  165. nci.pMsg = pMsg;
  166. HrSetAccount(pMsg, szAccount);
  167. // Create the note.
  168. hr = HrCreateNote(&nci);
  169. }
  170. exit:
  171. SafeRelease(pNNTPServer);
  172. Uninitialize_RunDLL();
  173. if (FAILED(hr))
  174. AthMessageBoxW(GetDesktopWindow(),
  175. MAKEINTRESOURCEW(idsAthenaNews),
  176. MAKEINTRESOURCEW(idsErrNewsCantOpen),
  177. 0,
  178. MB_ICONEXCLAMATION | MB_OK);
  179. return hr;
  180. #else
  181. return( E_NOTIMPL );
  182. #endif //!WIN16
  183. }
  184. ///////////////////////////////////////////////////////////////////////
  185. //
  186. // FUNCTION: HandleNewsURL
  187. //
  188. // PURPOSE: Provides an entry point into Thor that allows us to be
  189. // invoked from a URL. The pszCmdLine paramter must be a
  190. // valid News URL or nothing happens.
  191. //
  192. ///////////////////////////////////////////////////////////////////////
  193. HRESULT HandleNewsURL(LPTSTR pszCmd)
  194. {
  195. #ifndef WIN16 //RUN16_NEWS
  196. LPTSTR pszCmdLine = NULL;
  197. HRESULT hr = E_FAIL;
  198. LPTSTR pszServer = 0, pszGroup = 0, pszArticle = 0;
  199. UINT uPort = (UINT) -1;
  200. BOOL fSecure;
  201. ULONG cchCmdLine;
  202. cchCmdLine = 2 + lstrlen(pszCmd);
  203. if (!MemAlloc((LPVOID*) &pszCmdLine, cchCmdLine * sizeof(TCHAR)))
  204. goto exit;
  205. StrCpyN(pszCmdLine, pszCmd, cchCmdLine);
  206. UrlUnescapeInPlace(pszCmdLine, 0);
  207. DOUTL(1, TEXT("HandleNewsURL - pszCmdLine = %s"), pszCmdLine);
  208. if (!pszCmdLine || !*pszCmdLine)
  209. goto exit;
  210. // Figure out if the URL is valid and what type of URL it is.
  211. if (FAILED (URL_ParseNewsUrls(pszCmdLine, &pszServer, &uPort, &pszGroup, &pszArticle, &fSecure)))
  212. goto exit;
  213. if (uPort == -1)
  214. uPort = fSecure ? DEF_SNEWSPORT : DEF_NNTPPORT;
  215. if (pszArticle)
  216. {
  217. HandleNewsArticleURL(pszServer, pszArticle, uPort, fSecure);
  218. hr = S_OK;
  219. }
  220. else
  221. {
  222. LPITEMIDLIST pidl = NULL;
  223. ShellUtil_PidlFromNewsURL(pszServer, uPort, pszGroup, fSecure, &pidl);
  224. hr = BrowseToObject(pidl);
  225. if (pidl)
  226. PidlFree(pidl);
  227. }
  228. exit:
  229. if (pszCmdLine)
  230. MemFree(pszCmdLine);
  231. if (pszServer)
  232. MemFree(pszServer);
  233. if (pszGroup)
  234. MemFree(pszGroup);
  235. if (pszArticle)
  236. MemFree(pszArticle);
  237. if (FAILED(hr))
  238. AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsNewsRundllFailed), 0,
  239. MB_ICONEXCLAMATION | MB_OK);
  240. return hr;
  241. #else
  242. return( E_NOTIMPL );
  243. #endif //!WIN16
  244. }
  245. ///////////////////////////////////////////////////////////////////////
  246. //
  247. // FUNCTION: HandleEMLFile
  248. //
  249. // PURPOSE: Used to open EML files.
  250. //
  251. ///////////////////////////////////////////////////////////////////////
  252. HRESULT HandleEMLFile(LPTSTR pszCmd)
  253. {
  254. LPMIMEMESSAGE pMsg=0;
  255. NCINFO nci;
  256. HRESULT hr = E_FAIL;
  257. int idsErr = idsMailRundllFailed;
  258. if (!pszCmd || !*pszCmd)
  259. goto exit;
  260. DOUTL(1, TEXT("HandleEMLFile - pszCmd = %s"), pszCmd);
  261. // Check to see the file is valid
  262. if ((UINT)GetFileAttributes (pszCmd) == (UINT)-1)
  263. {
  264. idsErr = idsErrNewsCantOpen;
  265. goto exit;
  266. }
  267. if (!Initialize_RunDLL(TRUE))
  268. goto exit;
  269. // Create new mail message
  270. if (SUCCEEDED(hr = HrCreateMessage(&pMsg)))
  271. {
  272. // OPIE: correct way load EML file thro' IPF???
  273. // Ensure that the string is ANSI.
  274. if (SUCCEEDED(hr = HrLoadMsgFromFile(pMsg, pszCmd)))
  275. {
  276. if (SUCCEEDED(hr = HandleSecurity(GetDesktopWindow(), pMsg)))
  277. {
  278. LPSTR lpszUnsent;
  279. // Show the note
  280. ZeroMemory(&nci, sizeof(NCINFO));
  281. nci.ntNote = ntReadNote;
  282. nci.pMsg = pMsg;
  283. if (MimeOleGetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_XUNSENT), NOFLAGS, &lpszUnsent) == S_OK)
  284. {
  285. if (*lpszUnsent)
  286. {
  287. nci.ntNote = ntSendNote;
  288. nci.dwFlags = NCF_SENDIMMEDIATE; //always on dllentry points...
  289. }
  290. SafeMimeOleFree(lpszUnsent);
  291. }
  292. if (SUCCEEDED(hr = HrCreateNote(&nci)))
  293. idsErr = 0;
  294. }
  295. }
  296. else
  297. idsErr = idsErrNewsCantOpen;
  298. pMsg->Release();
  299. }
  300. // Once the user quits or sends the note, we can quit.
  301. Uninitialize_RunDLL();
  302. exit:
  303. if (idsErr && hr != HR_E_ATHSEC_FAILED)
  304. AthMessageBoxW(GetDesktopWindow(),
  305. MAKEINTRESOURCEW(idsAthenaMail),
  306. MAKEINTRESOURCEW(idsErr),
  307. 0, MB_ICONEXCLAMATION | MB_OK);
  308. return (idsErr) ? E_FAIL : S_OK;
  309. }
  310. ///////////////////////////////////////////////////////////////////////
  311. //
  312. // FUNCTION: HandleMailURL
  313. //
  314. // PURPOSE: Provides an entry point into Thor that allows us to be
  315. // invoked from a URL. The pszCmdLine paramter must be a
  316. // valid Mail URL or nothing happens.
  317. //
  318. ///////////////////////////////////////////////////////////////////////
  319. HRESULT HandleMailURL(LPTSTR pszCmd)
  320. {
  321. LPMIMEMESSAGE pMsg = NULL;
  322. HRESULT hr = E_FAIL;
  323. if (!pszCmd || !*pszCmd)
  324. goto exit;
  325. // NOTE: no URLUnescape in this function - it must be done in URL_ParseMailTo to handle
  326. // URLs of the format:
  327. //
  328. // mailto:[email protected]?subject=AT%26T%3dBell&[email protected]
  329. //
  330. // so that the "AT%26T" is Unescaped into "AT&T=Bell" *AFTER* the "subject=AT%26T%3dBell&" blob is parsed.
  331. DOUTL(1, TEXT("HandleMailURL - pszCmd = %s"), pszCmd);
  332. if (SUCCEEDED(HrCreateMessage(&pMsg)))
  333. {
  334. if (SUCCEEDED(URL_ParseMailTo(pszCmd, pMsg)))
  335. {
  336. if (Initialize_RunDLL(TRUE))
  337. {
  338. NCINFO nci = {0};
  339. nci.ntNote = ntSendNote;
  340. nci.dwFlags = NCF_SENDIMMEDIATE; //always on dllentry points...
  341. nci.pMsg = pMsg;
  342. hr = HrCreateNote(&nci);
  343. Uninitialize_RunDLL();
  344. }
  345. }
  346. pMsg->Release();
  347. }
  348. exit:
  349. if (FAILED(hr))
  350. AthMessageBoxW(GetDesktopWindow(),
  351. MAKEINTRESOURCEW(idsAthenaMail),
  352. MAKEINTRESOURCEW(idsMailRundllFailed),
  353. 0,
  354. MB_ICONEXCLAMATION | MB_OK);
  355. return hr;
  356. }
  357. #ifndef WIN16 //RUN16_NEWS
  358. typedef struct tagARTDOWNDLG {
  359. CNNTPServer *pNNTPServer;
  360. LPTSTR pszArticle;
  361. LPMIMEMESSAGE pMsg;
  362. LPSTREAM pStream;
  363. DWORD dwID;
  364. BOOL fOK;
  365. } ARTDOWNDLG, * PARTDOWNDLG;
  366. #define DAD_SERVERCB (WM_USER + 100)
  367. INT_PTR CALLBACK DownloadArticleDlg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
  368. {
  369. PARTDOWNDLG pad = (PARTDOWNDLG)GetWindowLong(hwnd, DWL_USER);
  370. TCHAR szBuffer[CCHMAX_STRINGRES];
  371. TCHAR szRes[CCHMAX_STRINGRES];
  372. switch (msg)
  373. {
  374. case WM_INITDIALOG:
  375. {
  376. NNTPNOTIFY not = { NULL, hwnd, DAD_SERVERCB, 0 };
  377. HRESULT hr;
  378. // replace some strings in the group download dialog
  379. AthLoadString(idsDownloadArtTitle, szRes, sizeof(szRes));
  380. SetWindowText(hwnd, szRes);
  381. AthLoadString(idsDownloadArtMsg, szRes, sizeof(szRes));
  382. SetDlgItemText(hwnd, idcStatic1, szRes);
  383. CenterDialog(hwnd);
  384. Assert(lParam);
  385. pad = (PARTDOWNDLG)lParam;
  386. SetWindowLong(hwnd, DWL_USER, lParam);
  387. Animate_Open(GetDlgItem(hwnd, idcAnimation), idanCopyMsgs);
  388. Animate_Play(GetDlgItem(hwnd, idcAnimation), 0, -1, -1);
  389. AthLoadString(idsProgReceivedLines, szRes, sizeof(szRes));
  390. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szRes, 0);
  391. SetDlgItemText(hwnd, idcProgText, szBuffer);
  392. // start the group download
  393. if (SUCCEEDED(hr = pad->pNNTPServer->Article(&not, NULL, pad->pszArticle, pad->pStream)))
  394. {
  395. pad->dwID = not.dwID;
  396. SetForegroundWindow(hwnd);
  397. }
  398. else
  399. EndDialog(hwnd, 0);
  400. }
  401. return (TRUE);
  402. case WM_COMMAND:
  403. Assert(pad);
  404. if (GET_WM_COMMAND_ID(wParam, lParam) == IDCANCEL)
  405. {
  406. Animate_Stop(GetDlgItem(hwnd, idcAnimation));
  407. EndDialog(hwnd, 0);
  408. return TRUE;
  409. }
  410. break;
  411. case WM_DESTROY:
  412. Assert(pad);
  413. if (pad->dwID)
  414. pad->pNNTPServer->CancelRequest(pad->dwID);
  415. break;
  416. case DAD_SERVERCB:
  417. {
  418. LPNNTPRESPONSE pResp;
  419. CNNTPResponse *pNNTPResp;
  420. if (SUCCEEDED(pad->pNNTPServer->GetAsyncResult(lParam, &pNNTPResp)))
  421. {
  422. pNNTPResp->Get(&pResp);
  423. Assert(pResp->state == NS_ARTICLE);
  424. if (pResp->fDone)
  425. {
  426. if (SUCCEEDED(pResp->rIxpResult.hrResult))
  427. {
  428. pad->fOK = TRUE;
  429. }
  430. else
  431. {
  432. int ids;
  433. if (IXP_NNTP_NO_SUCH_ARTICLE_NUM == pResp->rIxpResult.uiServerError ||
  434. IXP_NNTP_NO_SUCH_ARTICLE_FOUND == pResp->rIxpResult.uiServerError)
  435. ids = idsErrNewsExpired;
  436. else
  437. ids = idsErrNewsCantOpen;
  438. AthMessageBoxW(hwnd,
  439. MAKEINTRESOURCEW(idsAthenaNews),
  440. MAKEINTRESOURCEW(ids),
  441. 0,
  442. MB_OK | MB_ICONEXCLAMATION);
  443. }
  444. pad->dwID = 0;
  445. EndDialog(hwnd, 0);
  446. }
  447. else
  448. {
  449. AthLoadString(idsProgReceivedLines, szRes, sizeof(szRes));
  450. wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szRes, pResp->rArticle.cLines);
  451. SetDlgItemText(hwnd, idcProgText, szBuffer);
  452. }
  453. pNNTPResp->Release();
  454. }
  455. }
  456. return (TRUE);
  457. }
  458. return FALSE;
  459. }
  460. HRESULT HrDownloadArticleDialog(CNNTPServer *pNNTPServer, LPTSTR pszArticle, LPMIMEMESSAGE *ppMsg)
  461. {
  462. HRESULT hr;
  463. ARTDOWNDLG add = { 0 };
  464. if (SUCCEEDED(hr = HrCreateMessage(&add.pMsg)))
  465. {
  466. if (SUCCEEDED(hr = MimeOleCreateVirtualStream(&add.pStream)))
  467. {
  468. add.pNNTPServer = pNNTPServer;
  469. add.pszArticle = pszArticle;
  470. DialogBoxParam(g_hLocRes,
  471. MAKEINTRESOURCE(iddDownloadGroups),
  472. NULL,
  473. DownloadArticleDlg,
  474. (LPARAM)&add);
  475. if (add.fOK)
  476. {
  477. add.pMsg->Load(add.pStream);
  478. *ppMsg = add.pMsg;
  479. (*ppMsg)->AddRef();
  480. hr = S_OK;
  481. }
  482. else
  483. hr = E_FAIL;
  484. add.pStream->Release();
  485. }
  486. else
  487. {
  488. AthMessageBoxW(NULL, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsMemory), 0, MB_OK | MB_ICONSTOP);
  489. }
  490. add.pMsg->Release();
  491. }
  492. else
  493. {
  494. AthMessageBoxW(NULL, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsMemory), 0, MB_OK | MB_ICONSTOP);
  495. }
  496. return hr;
  497. }
  498. ///////////////////////////////////////////////////////////////////////
  499. //
  500. // FUNCTION: LogOffRunDLL
  501. //
  502. // PURPOSE: Provides an entry point into Thor that allows us to
  503. // perform an ExitWindows in the context of another
  504. // process. This works around all kinds of nasty shutdown
  505. // behavior and differences between NT and Win95.
  506. //
  507. ///////////////////////////////////////////////////////////////////////
  508. void WINAPI FAR LogOffRunDLL(HWND hwndStub, HINSTANCE hInstance, LPTSTR pszCmd, int nCmdShow)
  509. {
  510. HRESULT hr = S_OK;
  511. IUserDatabase *pUserDB;
  512. // this is required because ShowWindow ignore the params on
  513. // on the first call per process - this causes our notes to
  514. // use the nCmdShow from WinExec. By calling here, we make
  515. // sure that ShowWindow respects our later calls. (EricAn)
  516. ShowWindow(hwndStub, SW_HIDE);
  517. OleInitialize(0);
  518. if (SUCCEEDED(CoCreateInstance(CLSID_LocalUsers, NULL, CLSCTX_INPROC_SERVER, IID_IUserDatabase, (LPVOID*)&pUserDB)))
  519. {
  520. hr = pUserDB->Authenticate(GetDesktopWindow(), LUA_DIALOG|LUA_FORNEXTLOGON, NULL, NULL, NULL);
  521. pUserDB->Release();
  522. }
  523. if (SUCCEEDED(hr))
  524. ExitWindowsEx(EWX_LOGOFF, 0);
  525. OleUninitialize();
  526. }
  527. #endif //!WIN16