|
|
//
// DLL.CPP - Dll initialization routines
//
#include "pch.hxx"
#include "strconst.h"
#include <shlguid.h>
#include "ourguid.h"
#include "globals.h"
#include "folder.h"
#include "newsview.h"
#include "mimeole.h"
#include "mimeutil.h"
#include "mailnote.h"
#include "newsnote.h"
#include "resource.h"
#include "init.h"
#include <store.h>
#include "url.h"
#include "shelutil.h"
#include <goptions.h>
#include "nnserver.h"
#include "storfldr.h" // IsThisNashville
#include "strconst.h"
#include "grplist.h"
#include "shlwapi.h"
#include "shlwapip.h"
#include <secutil.h>
#include <error.h>
#ifndef WIN16 //RUN16_MSLU
#include <msluapi.h>
#include <msluguid.h>
#endif //!WIN16
extern HRESULT BrowseToObject(LPCITEMIDLIST pidl); HRESULT HrOpenMessage(HFOLDER hfldr, MSGID msgid, LPMIMEMESSAGE *ppMsg); BOOL ParseFolderMsgId(LPSTR pszCmdLine, HFOLDER *phfldr, MSGID *pmsgid); HRESULT HrDownloadArticleDialog(CNNTPServer *pNNTPServer, LPTSTR pszArticle, LPMIMEMESSAGE *ppMsg);
///////////////////////////////////////////////////////////////////////
//
// FUNCTION: HandleNWSFile
//
// PURPOSE: Provides an entry point into Thor that allows us to be
// invoked from a URL. The pszCmdLine paramter must be a
// valid News URL or nothing happens.
//
///////////////////////////////////////////////////////////////////////
HRESULT HandleNWSFile(LPTSTR pszCmd) { #ifndef WIN16 //RUN16_NEWS
LPMIMEMESSAGE pMsg; int idsErr = idsNewsRundllFailed; NCINFO nci = { 0 };
if (!pszCmd|| !*pszCmd) goto exit; DOUTL(1, TEXT("HandleNWSFile - pszCmd = %s"), pszCmd);
if ((UINT)GetFileAttributes (pszCmd) == (UINT)-1) { idsErr = idsErrNewsCantOpen; goto exit; }
// Do the basic DLL initialization first.
if (!Initialize_RunDLL(FALSE)) goto exit; // Create new message
if (SUCCEEDED(HrCreateMessage(&pMsg))) { if (SUCCEEDED(HrLoadMsgFromFile(pMsg, pszCmd))) { LPSTR lpszUnsent;
nci.ntNote = ntReadNote; nci.dwFlags = NCF_NEWS; nci.pMsg = pMsg;
if (MimeOleGetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_XUNSENT), NOFLAGS, &lpszUnsent) == S_OK) { if (*lpszUnsent) nci.ntNote = ntSendNote; SafeMimeOleFree(lpszUnsent); }
if (SUCCEEDED(HrCreateNote(&nci))) idsErr = 0; } else idsErr = idsErrNewsCantOpen; pMsg->Release(); }
Uninitialize_RunDLL();
exit: if (idsErr) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsErr), 0, MB_ICONEXCLAMATION | MB_OK); return (idsErr) ? E_FAIL : S_OK; #else
return( E_NOTIMPL ); #endif //!WIN16
}
///////////////////////////////////////////////////////////////////////
//
// FUNCTION: HandleNewsArticleURL
//
// PURPOSE: Provides an entry point into Thor that allows us to be
// invoked from a URL. The pszCmdLine paramter must be a
// valid News URL or nothing happens.
//
///////////////////////////////////////////////////////////////////////
HRESULT HandleNewsArticleURL(LPTSTR pszServerIn, LPTSTR pszArticle, UINT uPort, BOOL fSecure) { #ifndef WIN16 //RUN16_NEWS
NCINFO nci; CNNTPServer *pNNTPServer = NULL; HRESULT hr = E_FAIL; TCHAR szAccount[CCHMAX_ACCOUNT_NAME]; TCHAR szArticleId[1024]; IImnAccount *pAcct = NULL; LPMIMEMESSAGE pMsg = NULL;
// The URL specified an article id. In this case we ONLY want to
// display a ReadNote window. This requires a bit of work.
// Do the basic DLL initialization first.
if (!Initialize_RunDLL(FALSE)) { AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsNewsRundllFailed), 0, MB_ICONEXCLAMATION | MB_OK); return E_FAIL; } // If a server was specified, then try to create a temp account for it
if (pszServerIn && *pszServerIn && SUCCEEDED(NewsUtil_CreateTempAccount(pszServerIn, uPort, fSecure, &pAcct))) { pAcct->GetPropSz(AP_ACCOUNT_NAME, szAccount, ARRAYSIZE(szAccount)); pAcct->Release(); } else { // If a server wasn't specified, then use the default account
if (NewsUtil_GetDefaultServer(szAccount, ARRAYSIZE(szAccount)) != S_OK) goto exit; }
// Need to invoke read note. First create and initialize an server.
pNNTPServer = new CNNTPServer(); if (!pNNTPServer) goto exit; if (FAILED(pNNTPServer->HrInit(szAccount))) goto exit;
if (FAILED(pNNTPServer->Connect())) goto exit;
// Bug #10555 - The URL shouldn't have <> around the article ID, but some
// lameoids probably will do it anyway, so deal with it.
StrCpyN(szArticleId, pszArticle, ARRAYSIZE(szArticleId)); if (!IsDBCSLeadByte(*pszArticle)) { if (*pszArticle != '<') wnsprintf(szArticleId, ARRAYSIZE(szArticleId), TEXT("<%s>"), pszArticle); }
if (SUCCEEDED(hr = HrDownloadArticleDialog(pNNTPServer, szArticleId, &pMsg))) { // Initialize the NNCI struct so we can invoke a note window.
ZeroMemory(&nci, sizeof(NCINFO)); nci.ntNote = ntReadNote; nci.dwFlags = NCF_NEWS; nci.pMsg = pMsg; HrSetAccount(pMsg, szAccount);
// Create the note.
hr = HrCreateNote(&nci); }
exit: SafeRelease(pNNTPServer); Uninitialize_RunDLL();
if (FAILED(hr)) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsErrNewsCantOpen), 0, MB_ICONEXCLAMATION | MB_OK); return hr; #else
return( E_NOTIMPL ); #endif //!WIN16
}
///////////////////////////////////////////////////////////////////////
//
// FUNCTION: HandleNewsURL
//
// PURPOSE: Provides an entry point into Thor that allows us to be
// invoked from a URL. The pszCmdLine paramter must be a
// valid News URL or nothing happens.
//
///////////////////////////////////////////////////////////////////////
HRESULT HandleNewsURL(LPTSTR pszCmd) { #ifndef WIN16 //RUN16_NEWS
LPTSTR pszCmdLine = NULL; HRESULT hr = E_FAIL; LPTSTR pszServer = 0, pszGroup = 0, pszArticle = 0; UINT uPort = (UINT) -1; BOOL fSecure; ULONG cchCmdLine;
cchCmdLine = 2 + lstrlen(pszCmd); if (!MemAlloc((LPVOID*) &pszCmdLine, cchCmdLine * sizeof(TCHAR))) goto exit; StrCpyN(pszCmdLine, pszCmd, cchCmdLine); UrlUnescapeInPlace(pszCmdLine, 0);
DOUTL(1, TEXT("HandleNewsURL - pszCmdLine = %s"), pszCmdLine);
if (!pszCmdLine || !*pszCmdLine) goto exit; // Figure out if the URL is valid and what type of URL it is.
if (FAILED (URL_ParseNewsUrls(pszCmdLine, &pszServer, &uPort, &pszGroup, &pszArticle, &fSecure))) goto exit;
if (uPort == -1) uPort = fSecure ? DEF_SNEWSPORT : DEF_NNTPPORT;
if (pszArticle) { HandleNewsArticleURL(pszServer, pszArticle, uPort, fSecure); hr = S_OK; } else { LPITEMIDLIST pidl = NULL; ShellUtil_PidlFromNewsURL(pszServer, uPort, pszGroup, fSecure, &pidl); hr = BrowseToObject(pidl); if (pidl) PidlFree(pidl); } exit: if (pszCmdLine) MemFree(pszCmdLine); if (pszServer) MemFree(pszServer); if (pszGroup) MemFree(pszGroup); if (pszArticle) MemFree(pszArticle);
if (FAILED(hr)) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsNewsRundllFailed), 0, MB_ICONEXCLAMATION | MB_OK); return hr; #else
return( E_NOTIMPL ); #endif //!WIN16
}
///////////////////////////////////////////////////////////////////////
//
// FUNCTION: HandleEMLFile
//
// PURPOSE: Used to open EML files.
//
///////////////////////////////////////////////////////////////////////
HRESULT HandleEMLFile(LPTSTR pszCmd) { LPMIMEMESSAGE pMsg=0; NCINFO nci; HRESULT hr = E_FAIL; int idsErr = idsMailRundllFailed;
if (!pszCmd || !*pszCmd) goto exit; DOUTL(1, TEXT("HandleEMLFile - pszCmd = %s"), pszCmd);
// Check to see the file is valid
if ((UINT)GetFileAttributes (pszCmd) == (UINT)-1) { idsErr = idsErrNewsCantOpen; goto exit; }
if (!Initialize_RunDLL(TRUE)) goto exit;
// Create new mail message
if (SUCCEEDED(hr = HrCreateMessage(&pMsg))) { // OPIE: correct way load EML file thro' IPF???
// Ensure that the string is ANSI.
if (SUCCEEDED(hr = HrLoadMsgFromFile(pMsg, pszCmd))) { if (SUCCEEDED(hr = HandleSecurity(GetDesktopWindow(), pMsg))) { LPSTR lpszUnsent;
// Show the note
ZeroMemory(&nci, sizeof(NCINFO)); nci.ntNote = ntReadNote; nci.pMsg = pMsg; if (MimeOleGetBodyPropA(pMsg, HBODY_ROOT, PIDTOSTR(PID_HDR_XUNSENT), NOFLAGS, &lpszUnsent) == S_OK) { if (*lpszUnsent) { nci.ntNote = ntSendNote; nci.dwFlags = NCF_SENDIMMEDIATE; //always on dllentry points...
} SafeMimeOleFree(lpszUnsent); }
if (SUCCEEDED(hr = HrCreateNote(&nci))) idsErr = 0; } } else idsErr = idsErrNewsCantOpen; pMsg->Release(); }
// Once the user quits or sends the note, we can quit.
Uninitialize_RunDLL();
exit: if (idsErr && hr != HR_E_ATHSEC_FAILED) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsErr), 0, MB_ICONEXCLAMATION | MB_OK); return (idsErr) ? E_FAIL : S_OK; }
///////////////////////////////////////////////////////////////////////
//
// FUNCTION: HandleMailURL
//
// PURPOSE: Provides an entry point into Thor that allows us to be
// invoked from a URL. The pszCmdLine paramter must be a
// valid Mail URL or nothing happens.
//
///////////////////////////////////////////////////////////////////////
HRESULT HandleMailURL(LPTSTR pszCmd) { LPMIMEMESSAGE pMsg = NULL; HRESULT hr = E_FAIL;
if (!pszCmd || !*pszCmd) goto exit;
// NOTE: no URLUnescape in this function - it must be done in URL_ParseMailTo to handle
// URLs of the format:
//
// mailto:[email protected]?subject=AT%26T%3dBell&[email protected]
//
// so that the "AT%26T" is Unescaped into "AT&T=Bell" *AFTER* the "subject=AT%26T%3dBell&" blob is parsed.
DOUTL(1, TEXT("HandleMailURL - pszCmd = %s"), pszCmd);
if (SUCCEEDED(HrCreateMessage(&pMsg))) { if (SUCCEEDED(URL_ParseMailTo(pszCmd, pMsg))) { if (Initialize_RunDLL(TRUE)) { NCINFO nci = {0};
nci.ntNote = ntSendNote; nci.dwFlags = NCF_SENDIMMEDIATE; //always on dllentry points...
nci.pMsg = pMsg;
hr = HrCreateNote(&nci);
Uninitialize_RunDLL(); } } pMsg->Release(); }
exit: if (FAILED(hr)) AthMessageBoxW(GetDesktopWindow(), MAKEINTRESOURCEW(idsAthenaMail), MAKEINTRESOURCEW(idsMailRundllFailed), 0, MB_ICONEXCLAMATION | MB_OK); return hr; }
#ifndef WIN16 //RUN16_NEWS
typedef struct tagARTDOWNDLG { CNNTPServer *pNNTPServer; LPTSTR pszArticle; LPMIMEMESSAGE pMsg; LPSTREAM pStream; DWORD dwID; BOOL fOK; } ARTDOWNDLG, * PARTDOWNDLG;
#define DAD_SERVERCB (WM_USER + 100)
INT_PTR CALLBACK DownloadArticleDlg(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) { PARTDOWNDLG pad = (PARTDOWNDLG)GetWindowLong(hwnd, DWL_USER); TCHAR szBuffer[CCHMAX_STRINGRES]; TCHAR szRes[CCHMAX_STRINGRES];
switch (msg) { case WM_INITDIALOG: { NNTPNOTIFY not = { NULL, hwnd, DAD_SERVERCB, 0 }; HRESULT hr;
// replace some strings in the group download dialog
AthLoadString(idsDownloadArtTitle, szRes, sizeof(szRes)); SetWindowText(hwnd, szRes); AthLoadString(idsDownloadArtMsg, szRes, sizeof(szRes)); SetDlgItemText(hwnd, idcStatic1, szRes); CenterDialog(hwnd); Assert(lParam); pad = (PARTDOWNDLG)lParam; SetWindowLong(hwnd, DWL_USER, lParam);
Animate_Open(GetDlgItem(hwnd, idcAnimation), idanCopyMsgs); Animate_Play(GetDlgItem(hwnd, idcAnimation), 0, -1, -1); AthLoadString(idsProgReceivedLines, szRes, sizeof(szRes)); wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szRes, 0); SetDlgItemText(hwnd, idcProgText, szBuffer); // start the group download
if (SUCCEEDED(hr = pad->pNNTPServer->Article(¬, NULL, pad->pszArticle, pad->pStream))) { pad->dwID = not.dwID; SetForegroundWindow(hwnd); } else EndDialog(hwnd, 0); } return (TRUE); case WM_COMMAND: Assert(pad); if (GET_WM_COMMAND_ID(wParam, lParam) == IDCANCEL) { Animate_Stop(GetDlgItem(hwnd, idcAnimation)); EndDialog(hwnd, 0); return TRUE; } break; case WM_DESTROY: Assert(pad); if (pad->dwID) pad->pNNTPServer->CancelRequest(pad->dwID); break;
case DAD_SERVERCB: { LPNNTPRESPONSE pResp; CNNTPResponse *pNNTPResp;
if (SUCCEEDED(pad->pNNTPServer->GetAsyncResult(lParam, &pNNTPResp))) { pNNTPResp->Get(&pResp);
Assert(pResp->state == NS_ARTICLE); if (pResp->fDone) { if (SUCCEEDED(pResp->rIxpResult.hrResult)) { pad->fOK = TRUE; } else { int ids; if (IXP_NNTP_NO_SUCH_ARTICLE_NUM == pResp->rIxpResult.uiServerError || IXP_NNTP_NO_SUCH_ARTICLE_FOUND == pResp->rIxpResult.uiServerError) ids = idsErrNewsExpired; else ids = idsErrNewsCantOpen;
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(ids), 0, MB_OK | MB_ICONEXCLAMATION);
} pad->dwID = 0; EndDialog(hwnd, 0); } else { AthLoadString(idsProgReceivedLines, szRes, sizeof(szRes)); wnsprintf(szBuffer, ARRAYSIZE(szBuffer), szRes, pResp->rArticle.cLines); SetDlgItemText(hwnd, idcProgText, szBuffer); }
pNNTPResp->Release(); } } return (TRUE); } return FALSE; }
HRESULT HrDownloadArticleDialog(CNNTPServer *pNNTPServer, LPTSTR pszArticle, LPMIMEMESSAGE *ppMsg) { HRESULT hr; ARTDOWNDLG add = { 0 };
if (SUCCEEDED(hr = HrCreateMessage(&add.pMsg))) { if (SUCCEEDED(hr = MimeOleCreateVirtualStream(&add.pStream))) { add.pNNTPServer = pNNTPServer; add.pszArticle = pszArticle; DialogBoxParam(g_hLocRes, MAKEINTRESOURCE(iddDownloadGroups), NULL, DownloadArticleDlg, (LPARAM)&add); if (add.fOK) { add.pMsg->Load(add.pStream); *ppMsg = add.pMsg; (*ppMsg)->AddRef(); hr = S_OK; } else hr = E_FAIL; add.pStream->Release(); } else { AthMessageBoxW(NULL, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsMemory), 0, MB_OK | MB_ICONSTOP); } add.pMsg->Release(); } else { AthMessageBoxW(NULL, MAKEINTRESOURCEW(idsAthenaNews), MAKEINTRESOURCEW(idsMemory), 0, MB_OK | MB_ICONSTOP); }
return hr; }
///////////////////////////////////////////////////////////////////////
//
// FUNCTION: LogOffRunDLL
//
// PURPOSE: Provides an entry point into Thor that allows us to
// perform an ExitWindows in the context of another
// process. This works around all kinds of nasty shutdown
// behavior and differences between NT and Win95.
//
///////////////////////////////////////////////////////////////////////
void WINAPI FAR LogOffRunDLL(HWND hwndStub, HINSTANCE hInstance, LPTSTR pszCmd, int nCmdShow) { HRESULT hr = S_OK; IUserDatabase *pUserDB;
// this is required because ShowWindow ignore the params on
// on the first call per process - this causes our notes to
// use the nCmdShow from WinExec. By calling here, we make
// sure that ShowWindow respects our later calls. (EricAn)
ShowWindow(hwndStub, SW_HIDE);
OleInitialize(0);
if (SUCCEEDED(CoCreateInstance(CLSID_LocalUsers, NULL, CLSCTX_INPROC_SERVER, IID_IUserDatabase, (LPVOID*)&pUserDB))) { hr = pUserDB->Authenticate(GetDesktopWindow(), LUA_DIALOG|LUA_FORNEXTLOGON, NULL, NULL, NULL); pUserDB->Release(); } if (SUCCEEDED(hr)) ExitWindowsEx(EWX_LOGOFF, 0);
OleUninitialize(); }
#endif //!WIN16
|