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.
1424 lines
45 KiB
1424 lines
45 KiB
#include "pch.hxx"
|
|
#include <winuser.h>
|
|
#include <hlink.h>
|
|
#include <shellapi.h>
|
|
#define INITGUID
|
|
#include <initguid.h>
|
|
#include <exdisp.h>
|
|
#include <tchar.h>
|
|
|
|
BOOL IsNtSetupRunning()
|
|
{
|
|
BOOL fSetupRunning = FALSE;
|
|
DWORD dwSetupRunning;
|
|
DWORD cbValue = sizeof(dwSetupRunning);
|
|
long lResult = SHGetValue(HKEY_LOCAL_MACHINE, "system\\Setup", "SystemSetupInProgress", NULL, &dwSetupRunning, &cbValue);
|
|
|
|
if ((ERROR_SUCCESS == lResult) && (dwSetupRunning))
|
|
{
|
|
fSetupRunning = TRUE;
|
|
}
|
|
else
|
|
{
|
|
cbValue = sizeof(dwSetupRunning);
|
|
lResult = SHGetValue(HKEY_LOCAL_MACHINE, "system\\Setup", "UpgradeInProgress", NULL, &dwSetupRunning, &cbValue);
|
|
|
|
if ((ERROR_SUCCESS == lResult) && (dwSetupRunning))
|
|
{
|
|
fSetupRunning = TRUE;
|
|
}
|
|
}
|
|
|
|
return fSetupRunning;
|
|
}
|
|
|
|
#define ARRAYSIZE(buf) (sizeof(buf) / sizeof(buf[0]))
|
|
|
|
HINSTANCE g_hInstMAPI = NULL;
|
|
|
|
////////////////////////////////////////////////////////////////////////
|
|
//
|
|
// dll entry point
|
|
//
|
|
////////////////////////////////////////////////////////////////////////
|
|
STDAPI_(BOOL) APIENTRY DllMain(HINSTANCE hDll, DWORD dwReason, LPVOID lpRsrvd)
|
|
{
|
|
switch (dwReason)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
g_hInstMAPI = hDll;
|
|
break;
|
|
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
} // switch
|
|
return(TRUE);
|
|
}
|
|
|
|
BOOL FRunningOnNTEx(LPDWORD pdwVersion)
|
|
{
|
|
static BOOL fIsNT = 2 ;
|
|
static DWORD dwVersion = (DWORD)0;
|
|
OSVERSIONINFO VerInfo;
|
|
|
|
// If we have calculated this before just pass that back.
|
|
// else find it now.
|
|
//
|
|
if (fIsNT == 2)
|
|
{
|
|
VerInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
|
|
|
|
GetVersionEx(&VerInfo);
|
|
// Also, we don't check for failure on the above call as it
|
|
// should succeed if we are on NT 4.0 or Win 9X!
|
|
//
|
|
fIsNT = (VerInfo.dwPlatformId == VER_PLATFORM_WIN32_NT);
|
|
if (fIsNT)
|
|
dwVersion = VerInfo.dwMajorVersion;
|
|
}
|
|
if (pdwVersion)
|
|
*pdwVersion = dwVersion;
|
|
|
|
return fIsNT;
|
|
}
|
|
// Then next 2 functions are stollen from shlwapi. Needed to modiy them, because
|
|
// we had to handle SFN.
|
|
// Also there is a bug in the Ansi versin of ExpandEnvironmentStrings, where the
|
|
// function returns the number of bytes the string would have if it would be
|
|
// UNICODE. Since we have to convert the string anyway to SFN I use lstrlen to
|
|
// get the real length.
|
|
//
|
|
// If the given environment variable exists as the first part of the path,
|
|
// then the environment variable is inserted into the output buffer.
|
|
//
|
|
// Returns TRUE if pszResult is filled in.
|
|
//
|
|
// Example: Input -- C:\WINNT\SYSTEM32\FOO.TXT -and- lpEnvVar = %SYSTEMROOT%
|
|
// Output -- %SYSTEMROOT%\SYSTEM32\FOO.TXT
|
|
//
|
|
BOOL MyUnExpandEnvironmentString(LPCTSTR pszPath, LPCTSTR pszEnvVar, LPTSTR pszResult, UINT cbResult)
|
|
{
|
|
TCHAR szEnvVar[MAX_PATH];
|
|
DWORD dwEnvVar = SHExpandEnvironmentStrings(pszEnvVar, szEnvVar, ARRAYSIZE(szEnvVar));
|
|
|
|
if (dwEnvVar)
|
|
{
|
|
// Convert the string to short file name
|
|
GetShortPathName(szEnvVar, szEnvVar, ARRAYSIZE(szEnvVar));
|
|
dwEnvVar = lstrlen(szEnvVar);
|
|
if (CompareString(LOCALE_SYSTEM_DEFAULT, NORM_IGNORECASE, szEnvVar, dwEnvVar, pszPath, dwEnvVar) == 2)
|
|
{
|
|
if (lstrlen(pszPath) - (int)dwEnvVar + lstrlen(pszEnvVar) < (int)cbResult)
|
|
{
|
|
lstrcpy(pszResult, pszEnvVar);
|
|
lstrcat(pszResult, pszPath + dwEnvVar);
|
|
return TRUE;
|
|
}
|
|
}
|
|
}
|
|
return FALSE;
|
|
}
|
|
|
|
|
|
// note: %USERPROFILE% is relative to the user making the call, so this does
|
|
// not work if we are being impresonated from a service, for example
|
|
// dawrin installs apps from the system process this way
|
|
STDAPI_(BOOL) MyPathUnExpandEnvStrings(LPCTSTR pszPath, LPTSTR pszBuf, UINT cchBuf)
|
|
{
|
|
if (pszPath && pszBuf)
|
|
{
|
|
return (MyUnExpandEnvironmentString(pszPath, TEXT("%USERPROFILE%"), pszBuf, cchBuf) ||
|
|
MyUnExpandEnvironmentString(pszPath, TEXT("%ALLUSERSPROFILE%"), pszBuf, cchBuf) ||
|
|
MyUnExpandEnvironmentString(pszPath, TEXT("%ProgramFiles%"), pszBuf, cchBuf) ||
|
|
MyUnExpandEnvironmentString(pszPath, TEXT("%SystemRoot%"), pszBuf, cchBuf) ||
|
|
MyUnExpandEnvironmentString(pszPath, TEXT("%SystemDrive%"), pszBuf, cchBuf));
|
|
}
|
|
else
|
|
{
|
|
return FALSE;
|
|
}
|
|
}
|
|
|
|
|
|
#define POST_URL 0
|
|
#define INBOX_URL 1
|
|
// Return either the PostURL or the InboxURL depending on the value of nURL
|
|
//
|
|
static void GetPostUrl(int nURL, LPSTR lpszData, DWORD dwSize)
|
|
{
|
|
HKEY hkDefClient;
|
|
HKEY hkClient;
|
|
TCHAR szClient[64];
|
|
DWORD type;
|
|
DWORD dwClientSize = sizeof(TCHAR) * 64;
|
|
|
|
LONG err = RegOpenKey(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Clients\\Mail"), &hkClient);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = RegQueryValueEx(hkClient, NULL, 0, &type, (LPBYTE)szClient, &dwClientSize);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = RegOpenKey(hkClient, szClient, &hkDefClient);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
DWORD type;
|
|
err = RegQueryValueEx(hkDefClient,
|
|
nURL == POST_URL ? TEXT("posturl") : TEXT("inboxurl"),
|
|
0, &type, (LPBYTE)lpszData, &dwSize);
|
|
RegCloseKey(hkDefClient);
|
|
}
|
|
}
|
|
RegCloseKey(hkClient);
|
|
}
|
|
if (err != ERROR_SUCCESS)
|
|
{
|
|
LoadString(g_hInstMAPI,
|
|
nURL == POST_URL ? IDS_DEFAULTPOSTURL : IDS_DEFAULTINBOXURL,
|
|
lpszData, dwSize);
|
|
}
|
|
}
|
|
|
|
|
|
typedef HRESULT (STDAPICALLTYPE DynNavigate)(DWORD grfHLNF, LPBC pbc, IBindStatusCallback *pibsc,
|
|
LPCWSTR pszTargetFrame, LPCWSTR pszUrl, LPCWSTR pszLocation);
|
|
typedef DynNavigate FAR *LPDynNavigate;
|
|
|
|
STDAPI HlinkFrameNavigateNHL(DWORD grfHLNF, LPBC pbc, IBindStatusCallback *pibsc,
|
|
LPCWSTR pszTargetFrame, LPCWSTR pszUrl, LPCWSTR pszLocation)
|
|
{
|
|
HRESULT hr;
|
|
HINSTANCE hinst;
|
|
LPDynNavigate fpNavigate = NULL;
|
|
|
|
hinst = LoadLibraryA("SHDOCVW.DLL");
|
|
|
|
// If that failed because the module was not be found,
|
|
// then try to find the module in the directory we were
|
|
// loaded from.
|
|
|
|
if (!hinst)
|
|
goto Error;
|
|
|
|
fpNavigate = (LPDynNavigate)GetProcAddress(hinst, "HlinkFrameNavigateNHL");
|
|
if (!fpNavigate)
|
|
goto Error;
|
|
|
|
hr = fpNavigate(grfHLNF, pbc, pibsc, pszTargetFrame, pszUrl, pszLocation);
|
|
|
|
FreeLibrary(hinst);
|
|
return hr;
|
|
|
|
Error:
|
|
return GetLastError();
|
|
}
|
|
|
|
static void SimpleNavigate(LPTSTR lpszUrl, BOOL bUseFrame = false)
|
|
{
|
|
DWORD cch = (lstrlen(lpszUrl) + 1);
|
|
LPWSTR pwszData = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cch * sizeof(WCHAR));
|
|
if (pwszData)
|
|
{
|
|
SHTCharToUnicode(lpszUrl, pwszData, cch);
|
|
if (bUseFrame)
|
|
HlinkFrameNavigateNHL(HLNF_OPENINNEWWINDOW, NULL, NULL, NULL, pwszData, NULL);
|
|
else
|
|
HlinkSimpleNavigateToString(pwszData, NULL, NULL, NULL, NULL, NULL, 0, 0);
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pwszData);
|
|
}
|
|
}
|
|
|
|
// Pack some data into a SAFEARRAY of BYTEs. Return in a VARIANT
|
|
static HRESULT GetPostData(LPVARIANT pvPostData, LPTSTR lpszData)
|
|
{
|
|
HRESULT hr;
|
|
LPSAFEARRAY psa;
|
|
UINT cElems = lstrlen(lpszData);
|
|
LPSTR pPostData;
|
|
|
|
if (!pvPostData)
|
|
return E_POINTER;
|
|
|
|
VariantInit(pvPostData);
|
|
|
|
psa = SafeArrayCreateVector(VT_UI1, 0, cElems);
|
|
if (!psa)
|
|
return E_OUTOFMEMORY;
|
|
|
|
hr = SafeArrayAccessData(psa, (LPVOID*)&pPostData);
|
|
memcpy(pPostData, lpszData, cElems);
|
|
hr = SafeArrayUnaccessData(psa);
|
|
|
|
V_VT(pvPostData) = VT_ARRAY | VT_UI1;
|
|
V_ARRAY(pvPostData) = psa;
|
|
return NOERROR;
|
|
}
|
|
|
|
static void DoNavigate(LPTSTR lpszUrl, LPTSTR lpszData, BOOL bPlainIntf = TRUE)
|
|
{
|
|
HRESULT hr;
|
|
IWebBrowser2* pWBApp = NULL; // Derived from IWebBrowser
|
|
BSTR bstrURL = NULL, bstrHeaders = NULL;
|
|
VARIANT vFlags = {0};
|
|
VARIANT vTargetFrameName = {0};
|
|
VARIANT vPostData = {0};
|
|
VARIANT vHeaders = {0};
|
|
LPWSTR pwszData = NULL;
|
|
LPTSTR pszUrl = NULL;
|
|
DWORD cch;
|
|
|
|
if (FAILED(hr = CoInitialize(NULL)))
|
|
return;
|
|
|
|
if (FAILED(hr = CoCreateInstance(CLSID_InternetExplorer, NULL, CLSCTX_SERVER, IID_IWebBrowser2, (LPVOID*)&pWBApp)))
|
|
goto Error;
|
|
|
|
cch = lstrlen(lpszUrl) + lstrlen(lpszData) + 2;
|
|
pszUrl = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cch * sizeof(TCHAR));
|
|
if (!pszUrl)
|
|
goto Error;
|
|
lstrcpy(pszUrl, lpszUrl);
|
|
lstrcat(pszUrl, "?");
|
|
lstrcat(pszUrl, lpszData);
|
|
cch = lstrlen(pszUrl) + 1;
|
|
pwszData = (LPWSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cch * sizeof(WCHAR));
|
|
if (!pwszData)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pszUrl);
|
|
goto Error;
|
|
}
|
|
|
|
SHTCharToUnicode(pszUrl, pwszData, cch);
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pszUrl);
|
|
bstrURL = SysAllocString(pwszData);
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pwszData);
|
|
if (!bstrURL)
|
|
goto Error;
|
|
|
|
hr = pWBApp->Navigate(bstrURL, &vFlags, &vTargetFrameName, &vPostData, &vHeaders);
|
|
if (bPlainIntf)
|
|
{
|
|
pWBApp->put_AddressBar(VARIANT_FALSE);
|
|
pWBApp->put_MenuBar(VARIANT_FALSE);
|
|
pWBApp->put_ToolBar(VARIANT_FALSE);
|
|
}
|
|
pWBApp->put_Visible(VARIANT_TRUE);
|
|
|
|
Error:
|
|
if (bstrURL)
|
|
SysFreeString(bstrURL);
|
|
if (bstrHeaders)
|
|
SysFreeString(bstrHeaders);
|
|
VariantClear(&vPostData);
|
|
if (pWBApp)
|
|
pWBApp->Release();
|
|
CoUninitialize();
|
|
}
|
|
|
|
// Helpers for Form Submit - copied from IE3 and modified approriately
|
|
//
|
|
static char x_hex_digit(int c)
|
|
{
|
|
if (c >= 0 && c <= 9)
|
|
{
|
|
return c + '0';
|
|
}
|
|
if (c >= 10 && c <= 15)
|
|
{
|
|
return c - 10 + 'A';
|
|
}
|
|
return '0';
|
|
}
|
|
|
|
static const unsigned char isAcceptable[96] =
|
|
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
|
|
{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, /* 2x !"#$%&'()*+,-./ */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, /* 3x 0123456789:;<=>? */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 4x @ABCDEFGHIJKLMNO */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, /* 5x PQRSTUVWXYZ[\]^_ */
|
|
0, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, /* 6x `abcdefghijklmno */
|
|
1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0}; /* 7x pqrstuvwxyz{\}~ DEL */
|
|
|
|
// Performs URL-encoding of null-terminated strings. Pass NULL in pbOut
|
|
// to find buffer length required. Note that '\0' is not written out.
|
|
|
|
// 2/9/99 cchLimit param added for safety -- no more than cchLimit chars are
|
|
// written out. If pbOut is NULL then cchLimit is ignored. If the caller uses
|
|
// the style Buffer[URLEncode(Buffer, ...)] = 0, then cchLimit should be the
|
|
// buffer size minus one.
|
|
|
|
int
|
|
URLEncode(LPTSTR pbOut, const char * pchIn, const int cchLimit)
|
|
{
|
|
int lenOut = 0;
|
|
char * pchOut = (char *)pbOut;
|
|
|
|
for (; *pchIn && (!pchOut || lenOut < cchLimit); pchIn++, lenOut++)
|
|
{
|
|
if (*pchIn == ' ')
|
|
{
|
|
if (pchOut)
|
|
*pchOut++ = '+';
|
|
}
|
|
else if (*pchIn >= 32 && *pchIn <= 127 && isAcceptable[*pchIn - 32])
|
|
{
|
|
if (pchOut)
|
|
*pchOut++ = (TCHAR)*pchIn;
|
|
}
|
|
else
|
|
{
|
|
if (pchOut)
|
|
{
|
|
if (lenOut <= cchLimit - 3)
|
|
{
|
|
// enough room for this encoding
|
|
*pchOut++ = '%';
|
|
*pchOut++ = x_hex_digit((*pchIn >> 4) & 0xf);
|
|
*pchOut++ = x_hex_digit(*pchIn & 0xf);
|
|
lenOut += 2;
|
|
}
|
|
else
|
|
return lenOut;
|
|
}
|
|
else
|
|
lenOut += 2; // for expression handles 3rd inc
|
|
}
|
|
}
|
|
|
|
return lenOut;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPILogon
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPILogon(ULONG ulUIParam,
|
|
LPSTR lpszProfileName,
|
|
LPSTR lpszPassword,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved,
|
|
LPLHANDLE lplhSession)
|
|
{
|
|
*lplhSession = 1;
|
|
return SUCCESS_SUCCESS;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPILogoff
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPILogoff(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved)
|
|
{
|
|
return SUCCESS_SUCCESS;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPIFreeBuffer
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPIFreeBuffer(LPVOID lpv)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPISendMail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPISendMail(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
lpMapiMessage lpMessage,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved)
|
|
{
|
|
TCHAR szUrl[256];
|
|
|
|
GetPostUrl(POST_URL, szUrl, sizeof(TCHAR) * 256);
|
|
|
|
// Calculate the buffer size needed to create the url
|
|
ULONG i;
|
|
DWORD dwUrlSize = 32; // "?action=compose" + slop
|
|
DWORD dwMaxSize = 0;
|
|
DWORD dwSize;
|
|
DWORD dwFileSizes = 0;
|
|
HANDLE hFile;
|
|
|
|
if (lpMessage->lpszSubject)
|
|
{
|
|
dwSize = URLEncode(NULL, lpMessage->lpszSubject, 0);
|
|
dwMaxSize = max(dwMaxSize, dwSize + 1);
|
|
dwUrlSize += dwMaxSize + 9; // "&subject=%s"
|
|
}
|
|
if (lpMessage->lpszNoteText)
|
|
{
|
|
dwSize = URLEncode(NULL, lpMessage->lpszNoteText, 0);
|
|
dwMaxSize = max(dwMaxSize, dwSize + 1);
|
|
dwUrlSize += dwSize + 6; // "&body=%s"
|
|
}
|
|
|
|
for (i = 0; i < lpMessage->nRecipCount; i++)
|
|
{
|
|
dwSize = URLEncode(NULL, lpMessage->lpRecips[i].lpszName, 0);
|
|
dwMaxSize = max(dwMaxSize, dwSize + 1);
|
|
dwUrlSize += dwSize + 4; // "&to=%s" || "&cc=%s"
|
|
if (lpMessage->lpRecips[i].ulRecipClass == MAPI_BCC)
|
|
dwUrlSize++; // extra character for bcc
|
|
}
|
|
|
|
if (lpMessage->nFileCount)
|
|
{
|
|
dwUrlSize += 14; // "&filecount=xxx"
|
|
for (i = 0; i < lpMessage->nFileCount; i++)
|
|
{
|
|
if (!lpMessage->lpFiles[i].lpszPathName)
|
|
continue;
|
|
|
|
TCHAR szFileSize[32];
|
|
|
|
hFile = CreateFile(lpMessage->lpFiles[i].lpszPathName, 0 /*GENERIC_READ*/, 0 /*FILE_SHARE_READ*/, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
{
|
|
LPVOID lpMsgBuf = NULL;
|
|
FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, GetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPTSTR)&lpMsgBuf, 0, NULL);
|
|
if (lpMsgBuf)
|
|
{
|
|
MessageBox(NULL, (char*)lpMsgBuf, "Error", MB_OK | MB_ICONINFORMATION);
|
|
LocalFree(lpMsgBuf);
|
|
}
|
|
continue;
|
|
}
|
|
dwSize = GetFileSize(hFile, NULL);
|
|
CloseHandle(hFile);
|
|
if (dwSize == -1)
|
|
continue;
|
|
dwFileSizes += dwSize;
|
|
wnsprintf(szFileSize, ARRAYSIZE(szFileSize), "&size%d=%d", i, dwSize);
|
|
dwSize = lstrlen(szFileSize);
|
|
dwMaxSize = max(dwMaxSize, dwSize + 1);
|
|
dwUrlSize += dwSize;
|
|
|
|
|
|
dwSize = URLEncode(NULL, lpMessage->lpFiles[i].lpszPathName, 0) + 4; // in case we need to append a ^
|
|
dwMaxSize = max(dwMaxSize, dwSize + 1);
|
|
dwUrlSize += dwSize + 9; // "&pathxxx=%s"
|
|
|
|
if (lpMessage->lpFiles[i].lpszFileName)
|
|
{
|
|
dwSize = URLEncode(NULL, lpMessage->lpFiles[i].lpszFileName, 0);
|
|
dwMaxSize = max(dwMaxSize, dwSize + 1);
|
|
dwUrlSize += dwSize + 9; // "&filexxx=%s"
|
|
}
|
|
else
|
|
{
|
|
// ATTFILE code further down just tacks on the path when lpszFileName is NULL
|
|
dwUrlSize += URLEncode(NULL, lpMessage->lpFiles[i].lpszPathName, 0) + 4;
|
|
}
|
|
}
|
|
}
|
|
|
|
dwSize = ARRAYSIZE("&attfile=") + (URLEncode(NULL, "::", 0) * lpMessage->nFileCount * 3);
|
|
dwMaxSize = max(dwMaxSize, dwSize + 1);
|
|
dwUrlSize += dwSize;
|
|
|
|
LPTSTR pszData = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwUrlSize * sizeof(TCHAR));
|
|
|
|
if (!pszData)
|
|
return MAPI_E_FAILURE;
|
|
|
|
LPTSTR pszBuf = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwMaxSize * sizeof(TCHAR));
|
|
|
|
if (!pszBuf)
|
|
{
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID) pszData);
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
// Build the URL
|
|
lstrcpyn(pszData, "action=compose", dwUrlSize);
|
|
|
|
for (i = 0; i < lpMessage->nRecipCount; i++)
|
|
{
|
|
switch (lpMessage->lpRecips[i].ulRecipClass)
|
|
{
|
|
case MAPI_TO:
|
|
StrCatBuff(pszData, "&to=", dwUrlSize);
|
|
break;
|
|
case MAPI_CC:
|
|
StrCatBuff(pszData, "&cc=", dwUrlSize);
|
|
break;
|
|
case MAPI_BCC:
|
|
StrCatBuff(pszData, "&bcc=", dwUrlSize);
|
|
break;
|
|
}
|
|
pszBuf[URLEncode(pszBuf, lpMessage->lpRecips[i].lpszName, dwMaxSize-1)] = 0;
|
|
StrCatBuff(pszData, pszBuf, dwUrlSize);
|
|
}
|
|
if (lpMessage->lpszSubject)
|
|
{
|
|
StrCatBuff(pszData, "&subject=", dwUrlSize);
|
|
pszBuf[URLEncode(pszBuf, lpMessage->lpszSubject, dwMaxSize-1)] = 0;
|
|
StrCatBuff(pszData, pszBuf, dwUrlSize);
|
|
}
|
|
if (lpMessage->lpszNoteText)
|
|
{
|
|
StrCatBuff(pszData, "&body=", dwUrlSize);
|
|
pszBuf[URLEncode(pszBuf, lpMessage->lpszNoteText, dwMaxSize-1)] = 0;
|
|
StrCatBuff(pszData, pszBuf, dwUrlSize);
|
|
}
|
|
if (lpMessage->nFileCount)
|
|
{
|
|
TCHAR szSep[32];
|
|
TCHAR szPath[MAX_PATH];
|
|
TCHAR szTemp[MAX_PATH];
|
|
GetTempPath(MAX_PATH - 1, szTemp);
|
|
BOOL bIsTemp;
|
|
|
|
StrCatBuff(pszData, "&attfile=", dwUrlSize);
|
|
for (i = 0; i < lpMessage->nFileCount; i++)
|
|
{
|
|
if (!lpMessage->lpFiles[i].lpszPathName)
|
|
continue;
|
|
|
|
bIsTemp = FALSE;
|
|
lstrcpyn(szPath, lpMessage->lpFiles[i].lpszPathName, ARRAYSIZE(szPath));
|
|
hFile = CreateFile(szPath, 0, 0 /*GENERIC_READ, FILE_SHARE_READ*/, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (hFile == INVALID_HANDLE_VALUE)
|
|
continue;
|
|
dwSize = GetFileSize(hFile, NULL);
|
|
// Handle the case where this is a temporary file
|
|
if (CompareString(LOCALE_SYSTEM_DEFAULT, 0, szTemp, lstrlen(szTemp), szPath, lstrlen(szTemp)) == CSTR_EQUAL)
|
|
{
|
|
// If the file was created in the last 2 seconds assume that it is really temporary
|
|
FILETIME ftLastWrite, ftSystem;
|
|
LARGE_INTEGER liLastWrite, liSystem;
|
|
if (GetFileTime(hFile, NULL, NULL, &ftLastWrite))
|
|
{
|
|
GetSystemTimeAsFileTime(&ftSystem);
|
|
liLastWrite.LowPart = ftLastWrite.dwLowDateTime;
|
|
liLastWrite.HighPart = ftLastWrite.dwHighDateTime;
|
|
liSystem.LowPart = ftSystem.dwLowDateTime;
|
|
liSystem.HighPart = ftSystem.dwHighDateTime;
|
|
//jeffif (liLastWrite.QuadPart - liSystem.QuadPart < 30000000L)
|
|
bIsTemp = TRUE;
|
|
}
|
|
}
|
|
CloseHandle(hFile);
|
|
if (dwSize == -1)
|
|
continue;
|
|
if (bIsTemp)
|
|
{
|
|
StrCatBuff(szPath, "^", ARRAYSIZE(szPath));
|
|
MoveFile(lpMessage->lpFiles[i].lpszPathName, szPath);
|
|
SetFileAttributes(szPath, FILE_ATTRIBUTE_READONLY);
|
|
}
|
|
szSep[URLEncode(szSep, "::", ARRAYSIZE(szSep)-1)] = 0;
|
|
pszBuf[URLEncode(pszBuf, szPath, dwMaxSize-1)] = 0;
|
|
StrCatBuff(pszData, pszBuf, dwUrlSize);
|
|
StrCatBuff(pszData, szSep, dwUrlSize);
|
|
if (lpMessage->lpFiles[i].lpszFileName)
|
|
{
|
|
pszBuf[URLEncode(pszBuf, lpMessage->lpFiles[i].lpszFileName, dwMaxSize-1)] = 0;
|
|
StrCatBuff(pszData, pszBuf, dwUrlSize);
|
|
}
|
|
else
|
|
StrCatBuff(pszData, pszBuf, dwUrlSize);
|
|
StrCatBuff(pszData, szSep, dwUrlSize);
|
|
wnsprintf(szSep, ARRAYSIZE(szSep), "^%d;", dwSize);
|
|
pszBuf[URLEncode(pszBuf, szSep, dwMaxSize-1)] = 0;
|
|
StrCatBuff(pszData, pszBuf, dwUrlSize);
|
|
}
|
|
}
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pszBuf);
|
|
|
|
DoNavigate(szUrl, pszData, FALSE);
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pszData);
|
|
|
|
return SUCCESS_SUCCESS;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPISendDocuments
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPISendDocuments(ULONG ulUIParam,
|
|
LPSTR lpszDelimChar,
|
|
LPSTR lpszFullPaths,
|
|
LPSTR lpszFileNames,
|
|
ULONG ulReserved)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPIAddress
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPIAddress(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
LPTSTR lpszCaption,
|
|
ULONG nEditFields,
|
|
LPTSTR lpszLabels,
|
|
ULONG nRecips,
|
|
lpMapiRecipDesc lpRecips,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved,
|
|
LPULONG lpnNewRecips,
|
|
lpMapiRecipDesc FAR * lppNewRecips)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPIDetails
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPIDetails(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
lpMapiRecipDesc lpRecip,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPIResolveName
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPIResolveName(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
LPSTR lpszName,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved,
|
|
lpMapiRecipDesc FAR *lppRecip)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPIFindNext
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPIFindNext(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
LPSTR lpszMessageType,
|
|
LPSTR lpszSeedMessageID,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved,
|
|
LPSTR lpszMessageID)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPIReadMail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPIReadMail(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
LPSTR lpszMessageID,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved,
|
|
lpMapiMessage FAR *lppMessage)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPISaveMail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPISaveMail(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
lpMapiMessage lpMessage,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved,
|
|
LPSTR lpszMessageID)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MAPIDeleteMail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
ULONG FAR PASCAL MAPIDeleteMail(LHANDLE lhSession,
|
|
ULONG ulUIParam,
|
|
LPSTR lpszMessageID,
|
|
FLAGS flFlags,
|
|
ULONG ulReserved)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPISendMail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
BMAPI_ENTRY BMAPISendMail (LHANDLE hSession,
|
|
ULONG ulUIParam,
|
|
LPVB_MESSAGE lpM,
|
|
LPSAFEARRAY * lppsaRecips,
|
|
LPSAFEARRAY * lppsaFiles,
|
|
ULONG flFlags,
|
|
ULONG ulReserved)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPIFindNext
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
BMAPI_ENTRY BMAPIFindNext( LHANDLE hSession, // Session
|
|
ULONG ulUIParam, // UIParam
|
|
BSTR * lpbstrType, // MessageType
|
|
BSTR * lpbstrSeed, // Seed message Id
|
|
ULONG flFlags, // Flags
|
|
ULONG ulReserved, // Reserved
|
|
BSTR * lpbstrId)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPIReadMail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
BMAPI_ENTRY BMAPIReadMail( LPULONG lpulMessage, // pointer to output data (out)
|
|
LPULONG nRecips, // number of recipients (out)
|
|
LPULONG nFiles, // number of file attachments (out)
|
|
LHANDLE hSession, // Session
|
|
ULONG ulUIParam, // UIParam
|
|
BSTR * lpbstrID, // Message Id
|
|
ULONG flFlags, // Flags
|
|
ULONG ulReserved ) // Reserved
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPIGetReadMail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
BMAPI_ENTRY BMAPIGetReadMail( ULONG lpMessage, // Pointer to MAPI Mail
|
|
LPVB_MESSAGE lpvbMessage, // Pointer to VB Message Buffer (out)
|
|
LPSAFEARRAY * lppsaRecips, // Pointer to VB Recipient Buffer (out)
|
|
LPSAFEARRAY * lppsaFiles, // Pointer to VB File attachment Buffer (out)
|
|
LPVB_RECIPIENT lpvbOrig) // Pointer to VB Originator Buffer (out)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPISaveMail
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
BMAPI_ENTRY BMAPISaveMail( LHANDLE hSession, // Session
|
|
ULONG ulUIParam, // UIParam
|
|
LPVB_MESSAGE lpM, // Pointer to VB Message Buffer
|
|
LPSAFEARRAY * lppsaRecips, // Pointer to VB Recipient Buffer
|
|
LPSAFEARRAY * lppsaFiles, // Pointer to VB File Attacment Buffer
|
|
ULONG flFlags, // Flags
|
|
ULONG ulReserved, // Reserved
|
|
BSTR * lpbstrID) // Message ID
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPIAddress
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
BMAPI_ENTRY BMAPIAddress( LPULONG lpulRecip, // Pointer to New Recipient Buffer (out)
|
|
LHANDLE hSession, // Session
|
|
ULONG ulUIParam, // UIParam
|
|
BSTR * lpbstrCaption, // Caption string
|
|
ULONG ulEditFields, // Number of Edit Controls
|
|
BSTR * lpbstrLabel, // Label string
|
|
LPULONG lpulRecipients, // Pointer to number of Recipients (in/out)
|
|
LPSAFEARRAY * lppsaRecip, // Pointer to Initial Recipients VB_RECIPIENT
|
|
ULONG ulFlags, // Flags
|
|
ULONG ulReserved ) // Reserved
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPIGetAddress
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
BMAPI_ENTRY BMAPIGetAddress (ULONG ulRecipientData, // Pointer to recipient data
|
|
ULONG cRecipients, // Number of recipients
|
|
LPSAFEARRAY * lppsaRecips ) // VB recipient array
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPIDetails
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
BMAPI_ENTRY BMAPIDetails (LHANDLE hSession, // Session
|
|
ULONG ulUIParam, // UIParam
|
|
LPVB_RECIPIENT lpVB, // Pointer to VB recipient stucture
|
|
ULONG ulFlags, // Flags
|
|
ULONG ulReserved) // Reserved
|
|
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// BMAPIResolveName
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
BMAPI_ENTRY BMAPIResolveName (LHANDLE hSession, // Session
|
|
ULONG ulUIParam, // UIParam
|
|
BSTR bstrMapiName, // Name to be resolved
|
|
ULONG ulFlags, // Flags
|
|
ULONG ulReserved, // Reserved
|
|
LPVB_RECIPIENT lpVB) // Pointer to VB recipient structure (out)
|
|
{
|
|
return MAPI_E_FAILURE;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// MailToProtocolHandler
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void CALLBACK MailToProtocolHandler(HWND hwnd,
|
|
HINSTANCE hinst,
|
|
LPSTR lpszCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
TCHAR pszUrl[256];
|
|
|
|
GetPostUrl(POST_URL, pszUrl, sizeof(TCHAR) * 256);
|
|
LPTSTR pszData = (LPTSTR)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, (lstrlen(lpszCmdLine) + 32) * sizeof(TCHAR));
|
|
|
|
if (pszData)
|
|
{
|
|
wsprintf(pszData, "action=compose&to=%s", &lpszCmdLine[7]);
|
|
// Convert the extraneous '?' to '&'
|
|
for (LPTSTR p = pszData; *p; p++)
|
|
if (*p == '?')
|
|
*p = '&';
|
|
|
|
DoNavigate(pszUrl, pszData, FALSE);
|
|
|
|
HeapFree(GetProcessHeap(), 0, (LPVOID)pszData);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// OpenInboxHandler
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void CALLBACK OpenInboxHandler(HWND hwnd,
|
|
HINSTANCE hinst,
|
|
LPSTR lpszCmdLine,
|
|
int nCmdShow)
|
|
{
|
|
TCHAR pszUrl[256];
|
|
|
|
GetPostUrl(INBOX_URL, pszUrl, sizeof(TCHAR) * 256);
|
|
|
|
DoNavigate(pszUrl, "action=inbox", FALSE);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// Layout of Registry Usage
|
|
//
|
|
//
|
|
// HKEY_CLASSES_ROOT\mailto
|
|
// HKEY_CLASSES_ROOT\mailto\DefaultIcon
|
|
// HKEY_CLASSES_ROOT\mailto\shell\open\command
|
|
//
|
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail
|
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail\Hotmail
|
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail\Hotmail\Protocols\mailto
|
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail\Hotmail\Protocols\mailto\DefaultIcon
|
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail\Hotmail\Protocols\mailto\shell\open\command
|
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail\Hotmail\shell\open\command
|
|
// HKEY_LOCAL_MACHINE\SOFTWARE\Clients\Mail\Hotmail\backup
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
#define MAILTO TEXT("mailto")
|
|
#define PROTOCOLS TEXT("Protocols")
|
|
#define DEFAULTICON TEXT("DefaultIcon")
|
|
#define COMMAND TEXT("shell\\open\\command")
|
|
#define MAIL TEXT("SOFTWARE\\Clients\\Mail")
|
|
#define POSTURL TEXT("posturl")
|
|
#define BACKUP TEXT("backup")
|
|
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// SetRegStringValue
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
static LONG SetRegStringValue(HKEY hkKey, LPTSTR lpszKey, LPTSTR lpszValue, LPTSTR lpszPath, DWORD dwType)
|
|
{
|
|
if (!(dwType == REG_SZ) && !(dwType == REG_EXPAND_SZ))
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
if (lpszPath)
|
|
{
|
|
TCHAR szValue[MAX_PATH + 32];
|
|
wsprintf(szValue, lpszValue, lpszPath);
|
|
return RegSetValueEx(hkKey, lpszKey, 0, dwType, (LPBYTE)szValue, (lstrlen(szValue) + 1) * sizeof(TCHAR));
|
|
}
|
|
|
|
return RegSetValueEx(hkKey, lpszKey, 0, dwType, (LPBYTE)lpszValue, (lstrlen(lpszValue) + 1) * sizeof(TCHAR));
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// CreateMailToEntries
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
static LONG CreateMailToEntries(HKEY hkKey, TCHAR* lpszPath, BOOL fRegExpandSz)
|
|
{
|
|
LONG err;
|
|
HKEY hkMailToProt;
|
|
HKEY hkDefaultIcon;
|
|
HKEY hkCommand;
|
|
|
|
err = RegCreateKey(hkKey, MAILTO, &hkMailToProt);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = SetRegStringValue(hkMailToProt, NULL, TEXT("URL:MailTo Protocol"), NULL, REG_SZ);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
DWORD editFlags = 2;
|
|
err = RegSetValueEx(hkMailToProt, TEXT("EditFlags"), 0, REG_BINARY, (LPBYTE)&editFlags, sizeof(DWORD));
|
|
}
|
|
if (err == ERROR_SUCCESS)
|
|
err = SetRegStringValue(hkMailToProt, TEXT("URL Protocol"), TEXT(""), NULL, REG_SZ);
|
|
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegCreateKey(hkMailToProt, DEFAULTICON, &hkDefaultIcon);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = SetRegStringValue(hkDefaultIcon, NULL, "%s,1", lpszPath, fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
|
|
RegCloseKey(hkDefaultIcon);
|
|
}
|
|
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegCreateKey(hkMailToProt, COMMAND, &hkCommand);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwNTVer = 0;
|
|
// APPCOMPAT: Only the rundll32 on NT5 can handle double quotes around the path
|
|
// Lucky on Win9x and NT4 the epand sz path will never be a long file name and the old
|
|
// rundll32 works, but we cannot have double quotes
|
|
if (FRunningOnNTEx(&dwNTVer) && (dwNTVer >= 5))
|
|
{
|
|
err = SetRegStringValue(hkCommand, NULL, "rundll32.exe \"%s\",MailToProtocolHandler %%1", lpszPath, fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
|
|
}
|
|
else
|
|
{
|
|
err = SetRegStringValue(hkCommand, NULL, "rundll32.exe %s,MailToProtocolHandler %%1", lpszPath, fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
|
|
}
|
|
RegCloseKey(hkCommand);
|
|
}
|
|
RegCloseKey(hkMailToProt);
|
|
}
|
|
return err;
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DoAddService
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI DoAddService(LPSTR lpszService, LPSTR lpszPostURL)
|
|
{
|
|
LONG err;
|
|
TCHAR szLongPath[MAX_PATH];
|
|
TCHAR szPath[MAX_PATH];
|
|
HKEY hkClientsMail;
|
|
HKEY hkService;
|
|
HKEY hkProtocols;
|
|
HKEY hkCommand;
|
|
HKEY hkBackup;
|
|
BOOL fExistingMailClient = FALSE;
|
|
BOOL fRegExpandSz = FALSE;
|
|
|
|
GetModuleFileName(g_hInstMAPI, szLongPath, MAX_PATH); // get path to this DLL
|
|
GetShortPathName(szLongPath, szPath, MAX_PATH);
|
|
|
|
// First setup the info for the protocol in clients section
|
|
err = RegCreateKey(HKEY_LOCAL_MACHINE, MAIL, &hkClientsMail);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
fRegExpandSz = MyPathUnExpandEnvStrings(szPath, szLongPath, ARRAYSIZE(szLongPath));
|
|
if (fRegExpandSz)
|
|
lstrcpy(szPath, szLongPath);
|
|
err = RegCreateKey(hkClientsMail, lpszService, &hkService);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = SetRegStringValue(hkService, NULL, lpszService, NULL, REG_SZ);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = SetRegStringValue(hkService, TEXT("DLLPath"), szPath, NULL,
|
|
fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
|
|
}
|
|
if (err == ERROR_SUCCESS && lpszPostURL && lstrlen(lpszPostURL))
|
|
err = SetRegStringValue(hkService, TEXT("posturl"), lpszPostURL, NULL, REG_SZ);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegCreateKey(hkService, PROTOCOLS, &hkProtocols);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = CreateMailToEntries(hkProtocols, szPath, fRegExpandSz);
|
|
RegCloseKey(hkProtocols);
|
|
}
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegCreateKey(hkService, COMMAND, &hkCommand);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
DWORD dwNTVer = 0;
|
|
// APPCOMPAT: Only the rundll32 on NT5 can handle double quotes around the path
|
|
// Lucky on Win9x and NT4 the epand sz path will never be a long file name and the old
|
|
// rundll32 works, but we cannot have double quotes
|
|
if (FRunningOnNTEx(&dwNTVer) && (dwNTVer >= 5))
|
|
{
|
|
err = SetRegStringValue(hkCommand, NULL, "rundll32.exe \"%s\",OpenInboxHandler", szPath,
|
|
fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
|
|
}
|
|
else
|
|
{
|
|
err = SetRegStringValue(hkCommand, NULL, "rundll32.exe %s,OpenInboxHandler", szPath,
|
|
fRegExpandSz?REG_EXPAND_SZ:REG_SZ);
|
|
}
|
|
RegCloseKey(hkCommand);
|
|
}
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegCreateKey(hkService, BACKUP, &hkBackup);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
TCHAR szValue[MAX_PATH];
|
|
DWORD size;
|
|
DWORD type;
|
|
HKEY hkDefaultIcon;
|
|
HKEY hkCommand;
|
|
|
|
err = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("mailto\\DefaultIcon"), &hkDefaultIcon);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
size = sizeof(TCHAR) * MAX_PATH;
|
|
err = RegQueryValueEx(hkDefaultIcon, NULL, 0, &type, (LPBYTE)szValue, &size);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hkBackup, DEFAULTICON, 0, type, (LPBYTE)szValue, size);
|
|
RegCloseKey(hkDefaultIcon);
|
|
}
|
|
|
|
err = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("mailto\\shell\\open\\command"), &hkCommand);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
size = sizeof(TCHAR) * MAX_PATH;
|
|
err = RegQueryValueEx(hkCommand, NULL, 0, &type, (LPBYTE)szValue, &size);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
fExistingMailClient = TRUE;
|
|
err = RegSetValueEx(hkBackup, TEXT("command"), 0, type, (LPBYTE)szValue, size);
|
|
}
|
|
RegCloseKey(hkCommand);
|
|
}
|
|
|
|
size = sizeof(TCHAR) * MAX_PATH;
|
|
err = RegQueryValueEx(hkClientsMail, NULL, 0, &type, (LPBYTE)szValue, &size);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hkBackup, TEXT("mail"), 0, type, (LPBYTE)szValue, size);
|
|
|
|
RegCloseKey(hkBackup);
|
|
}
|
|
RegCloseKey(hkService);
|
|
}
|
|
if (err == ERROR_SUCCESS && !fExistingMailClient && !IsNtSetupRunning())
|
|
SetRegStringValue(hkClientsMail, NULL, lpszService, NULL, REG_SZ);
|
|
RegCloseKey(hkClientsMail);
|
|
}
|
|
if (err == ERROR_SUCCESS && !fExistingMailClient && !IsNtSetupRunning())
|
|
err = CreateMailToEntries(HKEY_CLASSES_ROOT, szPath, fRegExpandSz);
|
|
|
|
//
|
|
// REVIEW Backup fails sometimes. Need to clean up registry changes and
|
|
// probably remove all backup registry entirely.
|
|
// For now just safe to return S_OK
|
|
//
|
|
#if 0
|
|
if (err != ERROR_SUCCESS)
|
|
return HRESULT_FROM_WIN32(err);
|
|
#else
|
|
return S_OK;
|
|
#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DeleteKeyAndSubKeys
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
static LONG DeleteKeyAndSubKeys(HKEY hkIn, LPCTSTR pszSubKey)
|
|
{
|
|
HKEY hk;
|
|
TCHAR szTmp[MAX_PATH];
|
|
DWORD dwTmpSize;
|
|
long l;
|
|
int x;
|
|
|
|
l = RegOpenKeyEx(hkIn, pszSubKey, 0, KEY_ALL_ACCESS, &hk);
|
|
if (l != ERROR_SUCCESS)
|
|
return l;
|
|
|
|
// loop through all subkeys, blowing them away.
|
|
//
|
|
x = 0;
|
|
while (l == ERROR_SUCCESS)
|
|
{
|
|
dwTmpSize = MAX_PATH;
|
|
l = RegEnumKeyEx(hk, 0, szTmp, &dwTmpSize, 0, NULL, NULL, NULL);
|
|
if (l != ERROR_SUCCESS)
|
|
break;
|
|
|
|
l = DeleteKeyAndSubKeys(hk, szTmp);
|
|
}
|
|
|
|
// there are no subkeys left, [or we'll just generate an error and return FALSE].
|
|
// let's go blow this dude away.
|
|
//
|
|
RegCloseKey(hk);
|
|
return RegDeleteKey(hkIn, pszSubKey);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DoRemoveService
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI DoRemoveService(LPSTR lpszService)
|
|
{
|
|
TCHAR szValue[MAX_PATH];
|
|
DWORD size;
|
|
LONG err;
|
|
DWORD type;
|
|
HKEY hkDefaultIcon;
|
|
HKEY hkCommand;
|
|
HKEY hkBackup;
|
|
HKEY hkService;
|
|
HKEY hkClientsMail;
|
|
|
|
//
|
|
// Restore the previous values if HMMAPI is the current provider
|
|
//
|
|
err = RegOpenKey(HKEY_LOCAL_MACHINE, MAIL, &hkClientsMail);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Find the name of the current provider
|
|
//
|
|
TCHAR szCurrent[MAX_PATH];
|
|
DWORD cb = sizeof(szCurrent);
|
|
err = RegQueryValueEx(hkClientsMail, NULL, NULL, NULL, (LPBYTE)szCurrent, &cb);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
//
|
|
// Check if it is HMMAPI
|
|
//
|
|
if (StrCmp(szCurrent, lpszService) == 0)
|
|
{
|
|
err = RegOpenKey(hkClientsMail, lpszService, &hkService);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = RegOpenKey(hkService, BACKUP, &hkBackup);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
err = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("mailto\\DefaultIcon"), &hkDefaultIcon);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
size = sizeof(TCHAR) * MAX_PATH;
|
|
err = RegQueryValueEx(hkBackup, DEFAULTICON, 0, &type, (LPBYTE)szValue, &size);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hkDefaultIcon, NULL, 0, type, (LPBYTE)szValue, size);
|
|
RegCloseKey(hkDefaultIcon);
|
|
}
|
|
|
|
err = RegOpenKey(HKEY_CLASSES_ROOT, TEXT("mailto\\shell\\open\\command"), &hkCommand);
|
|
if (err == ERROR_SUCCESS)
|
|
{
|
|
size = sizeof(TCHAR) * MAX_PATH;
|
|
err = RegQueryValueEx(hkBackup, TEXT("command"), 0, &type, (LPBYTE)szValue, &size);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hkCommand, NULL, 0, type, (LPBYTE)szValue, size);
|
|
RegCloseKey(hkCommand);
|
|
}
|
|
|
|
size = sizeof(TCHAR) * MAX_PATH;
|
|
err = RegQueryValueEx(hkBackup, TEXT("mail"), 0, &type, (LPBYTE)szValue, &size);
|
|
if (err == ERROR_SUCCESS)
|
|
err = RegSetValueEx(hkClientsMail, NULL, 0, type, (LPBYTE)szValue, size);
|
|
|
|
RegCloseKey(hkBackup);
|
|
}
|
|
RegCloseKey(hkService);
|
|
}
|
|
}
|
|
err = DeleteKeyAndSubKeys(hkClientsMail, lpszService);
|
|
}
|
|
RegCloseKey(hkClientsMail);
|
|
}
|
|
|
|
//
|
|
// REVIEW Backup fails sometimes. Need to clean up registry changes and
|
|
// probably remove all backup registry entirely.
|
|
// For now just safe to return S_OK
|
|
//
|
|
#if 0
|
|
if (err != ERROR_SUCCESS)
|
|
return HRESULT_FROM_WIN32(err);
|
|
#else
|
|
return S_OK;
|
|
#endif
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// AddService
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void CALLBACK AddService(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
|
{
|
|
LPSTR lpszService = lpszCmdLine;
|
|
LPSTR lpszPostUrl = NULL;
|
|
|
|
if (*lpszService == '"')
|
|
{
|
|
lpszService++;
|
|
lpszPostUrl = StrChr(lpszService, '"');
|
|
if (lpszPostUrl)
|
|
{
|
|
*lpszPostUrl = 0;
|
|
lpszPostUrl++;
|
|
while (*lpszPostUrl && *lpszPostUrl == ' ')
|
|
lpszPostUrl++;
|
|
if (*lpszPostUrl == 0)
|
|
lpszPostUrl = NULL;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
lpszPostUrl = StrChr(lpszService, ' ');
|
|
if (lpszPostUrl)
|
|
{
|
|
*lpszPostUrl = 0;
|
|
lpszPostUrl++;
|
|
}
|
|
}
|
|
DoAddService(lpszService, lpszPostUrl);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// RemoveService
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
void CALLBACK RemoveService(HWND hwnd, HINSTANCE hinst, LPSTR lpszCmdLine, int nCmdShow)
|
|
{
|
|
DWORD dwLen = (lpszCmdLine) ? lstrlen(lpszCmdLine) : 0;
|
|
|
|
if (dwLen)
|
|
{
|
|
if (*lpszCmdLine == '"' && lpszCmdLine[dwLen - 1] == '"')
|
|
{
|
|
lpszCmdLine[dwLen - 1] = 0;
|
|
lpszCmdLine++;
|
|
}
|
|
DoRemoveService(lpszCmdLine);
|
|
}
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DllRegisterServer
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI DllRegisterServer(void)
|
|
{
|
|
return DoAddService(TEXT("Hotmail"), NULL);
|
|
}
|
|
|
|
///////////////////////////////////////////////////////////////////////
|
|
//
|
|
// DllUnregisterServer
|
|
//
|
|
///////////////////////////////////////////////////////////////////////
|
|
|
|
STDAPI DllUnregisterServer(void)
|
|
{
|
|
return DoRemoveService(TEXT("Hotmail"));
|
|
}
|