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.
 
 
 
 
 
 

1919 lines
56 KiB

// =================================================================================
// S T A T N E R Y . C P P
// =================================================================================
#include "pch.hxx"
#include "strconst.h"
#include "goptions.h"
#include "error.h"
#include "resource.h"
#include "mailutil.h"
#include "statnery.h"
#include "wininet.h"
#include "options.h"
#include <shlwapi.h>
#include <shlwapip.h>
#include "regutil.h"
#include "menuutil.h"
#include "thumb.h"
#include "optres.h"
#include <statwiz.h>
#include "url.h"
#include <bodyutil.h>
#include "demand.h"
#include "menures.h"
#include "ipab.h"
#include "mailnews.h"
#define STARTINDEX 0
#define CNOMORE 4
#define MAX_ENTRY 10
#define MAX_SHOWNAME 50
BOOL PASCAL MoreStationeryNotify(HWND hDlg, LPOFNOTIFYW pofn);
BOOL FHtmlFile(LPWSTR pwszFile);
BOOL CALLBACK MoreStationeryDlgHookProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
BOOL IsValidFileName(LPWSTR pwszFile);
void ShowBlankPreview(HWND hwnd);
HRESULT ShowMorePreview(HWND hwnd);
HRESULT FillHtmlToFileA(LPSTATWIZ pApp, HANDLE hFile, INT idsSample, BOOL fTemp);
HRESULT FillHtmlToFileW(LPSTATWIZ pApp, HANDLE hFile, INT idsSample, BOOL fTemp);
BOOL fValidFile(LPWSTR pwszFile);
BOOL fFileOK(LPWSTR pwszFile);
static WCHAR s_wszStationeryDir[MAX_PATH]={0};
static WCHAR g_wszLastStationeryPath[MAX_PATH];
static const HELPMAP g_rgStatWizHlp[] = {
{IDC_SHOWPREVIEW_BUTTON_ADD, IDH_STATIONERY_BROWSE_PICTURE },
{IDC_SHOWPREVIEW_BUTTON_EDIT, IDH_STATIONERY_EDIT },
{IDC_STATWIZ_PREVIEWBACKGROUND, IDH_STATIONERY_PREVIEW},
{IDC_MOREPREVIEW, 35640},
{IDC_SHOWPREVIEW_CHECK, 35656},
{0, 0}
};
const static CHAR c_szHtmlExtension[] = ".htm";
const static CHAR c_szTempFileName[] = "StatWiz";
static const WCHAR c_wszFile[] = L"File";
static const WCHAR c_wszRSFileFmt[] = L"%s%d";
const static WCHAR c_wszBlankHtml[] = L"blank.htm";
const static WCHAR c_wszEditCmd[] = L"edit";
const static WCHAR c_wszHtmlHeadFmt[] = L"<HTML>\r\n<HEAD>\r\n<STYLE>\r\nBODY {\r\n";
const static WCHAR c_wszStyleClose[] = L"}\r\n</STYLE>\r\n</HEAD>\r\n";
const static WCHAR c_wszBodyFmt[] = L"<BODY %s=\"%s\">\r\n";
const static WCHAR c_wszHtmlClose[] = L"</BODY>\r\n</HTML>\r\n";
const static WCHAR c_wszBkPicture[] = L"background";
const static WCHAR c_wszBkColor[] = L"bgcolor";
const static WCHAR c_wszFontFmt[] = L"font-family: %s;\r\nfont-size: %dpt;\r\ncolor: %s;\r\n";
const static WCHAR c_wszBold[] = L"font-weight: bold;\r\n";
const static WCHAR c_wszItalic[] = L"font-style: italic;\r\n";
const static WCHAR c_wszLeftMarginFmt[] = L"margin-left: %d px;\r\n";
const static WCHAR c_wszTopMarginFmt[] = L"margin-top: %d px;\r\n";
const static WCHAR c_wszFontFamily[] = L"font-family:";
const static WCHAR c_wszFontSize[] = L"font-size:";
const static WCHAR c_wszFontColor[] = L"color:";
const static WCHAR c_wszBkRepeat[] = L"background-repeat: %s;\r\n";
const static WCHAR c_wszBkPosition[] = L"background-position: %s;\r\n";
const static LPWSTR c_lppwszBkPos[3][3] = {
{L"top left", L"top center", L"top right"},
{L"center left", L"center center", L"center right"},
{L"bottom left", L"bottom center", L"bottom right"}};
static const LPWSTR c_rgpwszHTMLExtensions[] = {L"*.htm", L"*.html"};
const static LPWSTR c_lpwszRepeatPos[] = {L"no-repeat", L"repeat-y", L"repeat-x", L"repeat" };
static const LPWSTR c_wszPictureExtensions[] = {L"*.gif", L"*.bmp", L"*.jpg"};
const static CHAR c_szBlankHtml[] = "blank.htm";
const static CHAR c_szEditCmd[] = "edit";
const static CHAR c_szHtmlHeadFmt[] = "<HTML>\r\n<HEAD>\r\n<STYLE>\r\nBODY {\r\n";
const static CHAR c_szStyleClose[] = "}\r\n</STYLE>\r\n</HEAD>\r\n";
const static CHAR c_szBodyFmt[] = "<BODY %s=\"%s\">\r\n";
const static CHAR c_szHtmlClose[] = "</BODY>\r\n</HTML>\r\n";
const static CHAR c_szBkPicture[] = "background";
const static CHAR c_szBkColor[] = "bgcolor";
const static CHAR c_szFontFmt[] = "font-family: %s;\r\nfont-size: %dpt;\r\ncolor: %s;\r\n";
const static CHAR c_szBold[] = "font-weight: bold;\r\n";
const static CHAR c_szItalic[] = "font-style: italic;\r\n";
const static CHAR c_szLeftMarginFmt[] = "margin-left: %d px;\r\n";
const static CHAR c_szTopMarginFmt[] = "margin-top: %d px;\r\n";
const static CHAR c_szFontFamily[] = "font-family:";
const static CHAR c_szFontSize[] = "font-size:";
const static CHAR c_szFontColor[] = "color:";
const static CHAR c_szBkRepeat[] = "background-repeat: %s;\r\n";
const static CHAR c_szBkPosition[] = "background-position: %s;\r\n";
const static LPSTR c_lppszBkPos[3][3] = {
{"top left", "top center", "top right"},
{"center left", "center center", "center right"},
{"bottom left", "bottom center", "bottom right"}};
static const LPSTR c_rgpszHTMLExtensions[] = {"*.htm", "*.html"};
const static LPSTR c_lpszRepeatPos[] = {"no-repeat", "repeat-y", "repeat-x", "repeat" };
static const LPSTR c_szPictureExtensions[] = {"*.gif", "*.bmp", "*.jpg"};
/******************************************************************************************
* ListEntry
*******************************************************************************************/
ListEntry::ListEntry()
{
INT iLen;
m_cRef = 1;
m_pwszFile = NULL;
m_pNext = NULL;
}
HRESULT ListEntry::HrInit(LPWSTR pwszFile)
{
INT iLen;
HRESULT hr = S_OK;
if(NULL == pwszFile || *pwszFile == 0)
IF_FAILEXIT(hr = E_INVALIDARG);
#pragma prefast(suppress:11, "noise")
iLen = lstrlenW(pwszFile);
IF_NULLEXIT(MemAlloc((LPVOID*)&m_pwszFile, (iLen+1)*sizeof(WCHAR)));
StrCpyNW(m_pwszFile, pwszFile,iLen+1);
exit:
return hr;
}
ListEntry::~ListEntry()
{
MemFree(m_pwszFile);
m_pNext = NULL;
}
ULONG ListEntry::AddRef(VOID)
{
return ++m_cRef;
}
ULONG ListEntry::Release(VOID)
{
if (--m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
/******************************************************************************************
* CStationery
*******************************************************************************************/
CStationery::CStationery()
{
m_cRef = 1;
m_pFirst = NULL;
InitializeCriticalSection(&m_rCritSect);
}
CStationery::~CStationery()
{
Assert (m_cRef == 0);
while(S_OK==HrDeleteEntry(0));
DeleteCriticalSection(&m_rCritSect);
}
ULONG CStationery::AddRef(VOID)
{
return ++m_cRef;
}
ULONG CStationery::Release(VOID)
{
if (--m_cRef == 0)
{
delete this;
return 0;
}
return m_cRef;
}
// always insert at the beginning.
HRESULT CStationery::HrInsertEntry(LPWSTR pwszFile)
{
LPLISTENTRY pNewEntry = NULL;
HRESULT hr = S_OK;
if(!fFileOK(pwszFile))
return E_INVALIDARG;
EnterCriticalSection(&m_rCritSect);
IF_NULLEXIT(pNewEntry = new ListEntry);
IF_FAILEXIT(hr = pNewEntry->HrInit(pwszFile));
IF_FAILEXIT(hr = HrInsertEntry(pNewEntry));
pNewEntry = NULL; //prevent deleting.
exit:
LeaveCriticalSection(&m_rCritSect);
ReleaseObj(pNewEntry);
return hr;
}
HRESULT CStationery::HrInsertEntry(LPLISTENTRY pEntry)
{
HRESULT hr = S_OK;
if(NULL==pEntry || !fFileOK(pEntry->m_pwszFile))
return TraceResult(E_INVALIDARG);
EnterCriticalSection(&m_rCritSect);
if(cEntries()==MAX_ENTRY)
IF_FAILEXIT(hr = HrDeleteEntry(MAX_ENTRY-1));
if(NULL!=m_pFirst) //not empty
pEntry->m_pNext = m_pFirst;
m_pFirst = pEntry;
exit:
LeaveCriticalSection(&m_rCritSect);
return hr;
}
// iIndex is 0 based
HRESULT CStationery::HrPromoteEntry(INT iIndex)
{
HRESULT hr = NOERROR;
LPLISTENTRY pPromotedEntry = NULL;
if(iIndex == 0 || !fValidIndex(iIndex))
return TraceResult(E_INVALIDARG);
EnterCriticalSection(&m_rCritSect);
IF_NULLEXIT(pPromotedEntry = RemoveEntry(iIndex));
IF_FAILEXIT(hr = HrInsertEntry(pPromotedEntry));
exit:
LeaveCriticalSection(&m_rCritSect);
return hr;
}
LPLISTENTRY CStationery::MoveToEntry(INT iIndex)
{
LPLISTENTRY pEntry = NULL;
if(!fValidIndex(iIndex))
goto error;
pEntry = m_pFirst;
if(iIndex!=0)
{
for(INT i=0; i<iIndex; i++)
{
pEntry = pEntry->m_pNext;
Assert(pEntry);
}
}
error:
return pEntry;
}
LPLISTENTRY CStationery::RemoveEntry(INT iIndex)
{
LPLISTENTRY pRemovedEntry = NULL,
pEntry = m_pFirst;
if(!fValidIndex(iIndex))
goto error;
EnterCriticalSection(&m_rCritSect);
if(iIndex==0) //remove the first one,
{
pRemovedEntry = m_pFirst;
m_pFirst = pRemovedEntry->m_pNext;
}
else
{
pEntry = MoveToEntry(iIndex - 1);
pRemovedEntry = pEntry->m_pNext;
pEntry->m_pNext = pRemovedEntry ->m_pNext;
}
error:
LeaveCriticalSection(&m_rCritSect);
return pRemovedEntry;
}
HRESULT CStationery::HrDeleteEntry(INT iIndex)
{
HRESULT hr = NOERROR;
LPLISTENTRY pRemovedEntry = NULL;
if(!fValidIndex(iIndex))
return TraceResult(E_INVALIDARG);
EnterCriticalSection(&m_rCritSect);
pRemovedEntry = RemoveEntry(iIndex);
if (!pRemovedEntry)
IF_FAILEXIT(hr = E_FAIL);
exit:
ReleaseObj(pRemovedEntry);
LeaveCriticalSection(&m_rCritSect);
return hr;
}
VOID CStationery::ValidateList(BOOL fCheckExist)
{
HRESULT hr = NOERROR;
LPLISTENTRY pEntry = m_pFirst,
pPrev = NULL;
BOOL fValid = FALSE;
EnterCriticalSection(&m_rCritSect);
while(pEntry != NULL)
{
fValid = fCheckExist ? fValidFile(pEntry->m_pwszFile) : fFileOK(pEntry->m_pwszFile);
if(!fValid)
{
if(pEntry == m_pFirst)
{
m_pFirst = pEntry->m_pNext;
ReleaseObj(pEntry);
pEntry = m_pFirst;
}
else if (pPrev != NULL)
{
pPrev->m_pNext = pEntry->m_pNext;
ReleaseObj(pEntry);
pEntry = pPrev->m_pNext;
}
}
pPrev = pEntry;
if(pEntry)
pEntry = pEntry->m_pNext;
}
LeaveCriticalSection(&m_rCritSect);
return;
}
HRESULT CStationery::HrGetFileName(INT iIndex, LPWSTR pwszBuf)
{
HRESULT hr = NOERROR;
LPLISTENTRY pEntry = NULL;
if(!fValidIndex(iIndex) || NULL==pwszBuf)
return TraceResult(E_INVALIDARG);
pEntry = MoveToEntry(iIndex);
if (!pEntry)
IF_FAILEXIT(hr = E_FAIL);
#pragma prefast(suppress:11, "noise")
StrCpyNW(pwszBuf, pEntry->m_pwszFile, MAX_PATH);
exit:
return hr;
}
INT CStationery::cEntries()
{
INT iRet = 0;
LPLISTENTRY pEntry = m_pFirst;
while(pEntry != NULL)
{
pEntry = pEntry->m_pNext;
iRet++;
}
return iRet;
}
BOOL CStationery::fValidIndex(INT iIndex)
{
BOOL fRet = TRUE;
if(iIndex < 0 || iIndex > MAX_ENTRY)
fRet = FALSE;
if(cEntries()<=iIndex)
fRet = FALSE;
return fRet;
}
BOOL fFileOK(LPWSTR pwszFile)
{
BOOL fRet = FALSE;
if(pwszFile == NULL || *pwszFile == 0)
goto exit;
if (!FHtmlFile(pwszFile))
goto exit;
fRet = TRUE;
exit:
return fRet;
}
BOOL fValidFile(LPWSTR pwszFile)
{
BOOL fRet = FALSE;
WCHAR wszBuf[MAX_PATH];
DWORD dwAttributes;
*wszBuf = 0;
if(!fFileOK(pwszFile))
goto exit;
StrCpyNW(wszBuf, pwszFile, ARRAYSIZE(wszBuf));
InsertStationeryDir(wszBuf);
dwAttributes = GetFileAttributesWrapW(wszBuf);
if((UINT)dwAttributes==(UINT)-1 || dwAttributes&FILE_ATTRIBUTE_DIRECTORY)
goto exit;
fRet = TRUE;
exit:
return fRet;
}
HRESULT CStationery::HrFindEntry(LPWSTR pwszFile, INT* pRet)
{
INT iRet = -1, iIndex=0;
LPLISTENTRY pEntry = m_pFirst;
HRESULT hr = S_OK;
*pRet = iRet;
if(!fFileOK(pwszFile))
return TraceResult(E_INVALIDARG);
while(pEntry != NULL)
{
if(StrCmpW(pEntry->m_pwszFile, pwszFile) == 0)
{
iRet = iIndex;
break;
}
pEntry = pEntry->m_pNext;
iIndex++;
}
*pRet = iRet;
if(iRet==-1)
hr = E_FAIL;
return hr;
}
HRESULT CStationery::HrLoadStationeryList()
{
HRESULT hr = NOERROR;
INT i;
HKEY hkey=NULL;
DWORD dwType=0, cb=0, dw=0;
WCHAR wszFileName[INTERNET_MAX_URL_LENGTH];
WCHAR wszFileRegName[MAX_PATH];
LONG lRegResult;
*wszFileName = 0;
*wszFileRegName = 0;
lRegResult = AthUserOpenKey(c_szRegPathRSWideList, KEY_READ, &hkey);
// If we failed, then try and open up the old list.
if (ERROR_SUCCESS != lRegResult)
lRegResult = AthUserOpenKey(c_szRegPathRSList, KEY_READ, &hkey);
if (ERROR_SUCCESS == lRegResult)
{
for(i = MAX_ENTRY-1; i >= 0; i--)
{
wnsprintfW(wszFileRegName, ARRAYSIZE(wszFileRegName), c_wszRSFileFmt, c_wszFile, i);
cb = sizeof(wszFileName);
if(ERROR_SUCCESS == RegQueryValueExWrapW(hkey, wszFileRegName, 0,
&dwType, (LPBYTE)wszFileName, &cb))
{
hr = HrInsertEntry(wszFileName);
if (hr == E_OUTOFMEMORY)
break;
}
}
RegCloseKey(hkey);
}
if(E_OUTOFMEMORY != hr)
hr = NOERROR; //we only catch E_OUTOFMEMORY.
return hr;
}
void CStationery::SaveStationeryList()
{
INT index = 0;
HKEY hkey=NULL;
WCHAR wszFileRegName[MAX_PATH];
LPLISTENTRY pEntry = m_pFirst;
INT i;
DWORD dw;
*wszFileRegName = 0;
if (ERROR_SUCCESS == AthUserCreateKey(c_szRegPathRSWideList, KEY_WRITE, &hkey, &dw))
{
while(pEntry != NULL)
{
wnsprintfW(wszFileRegName, ARRAYSIZE(wszFileRegName), c_wszRSFileFmt, c_wszFile, index);
StripStationeryDir(pEntry->m_pwszFile);
if(pEntry->m_pwszFile && *(pEntry->m_pwszFile))
{
DWORD cb = (lstrlenW(pEntry->m_pwszFile) + 1) * sizeof(WCHAR);
RegSetValueExWrapW(hkey, wszFileRegName, 0, REG_SZ, (LPBYTE)(pEntry->m_pwszFile), cb);
index++;
}
pEntry = pEntry->m_pNext;
}
for(i = index; i < MAX_ENTRY; i++) // NULL the rest
{
wnsprintfW(wszFileRegName, ARRAYSIZE(wszFileRegName), c_wszRSFileFmt, c_wszFile, i);
RegSetValueExWrapW(hkey, wszFileRegName, 0, REG_SZ, (LPBYTE)c_wszEmpty, sizeof(WCHAR));
}
RegCloseKey(hkey);
}
}
HRESULT CStationery::HrGetShowNames(LPWSTR pwszFile, LPWSTR pwszShowName, int cchShowName, INT index)
{
HRESULT hr = S_OK;
LPWSTR pwsz = NULL;
INT iLen;
WCHAR wszBuf[MAX_PATH];
*wszBuf = 0;
if(pwszFile==NULL || *pwszFile==0 || pwszShowName==NULL)
IF_FAILEXIT(hr = E_INVALIDARG);
#pragma prefast(suppress:11, "noise")
iLen = lstrlenW(pwszFile);
*pwszShowName = 0;
PathCompactPathExW(wszBuf, pwszFile, MAX_SHOWNAME, 0);
if(*wszBuf == 0)
IF_FAILEXIT(hr = E_FAIL);
if(index == (MAX_ENTRY-1))
wnsprintfW(pwszShowName, cchShowName, c_wszNumberFmt10, wszBuf);
else
wnsprintfW(pwszShowName, cchShowName, c_wszNumberFmt, index+1, wszBuf);
// delete .htm and .html
PathRemoveExtensionW(pwszShowName);
exit:
return hr;
}
// Assumes that there are no other items on the menu that have to be numbered.
void CStationery::AddStationeryMenu(HMENU hmenu, int idFirst, int idMore)
{
INT iIndex = 0,
cNumIDs;
LPLISTENTRY pEntry = m_pFirst;
WCHAR wszBuf[MAX_PATH];
INT cMenus;
MENUITEMINFOW mii;
INT iInsertPos;
BOOL fInsertSep = FALSE;
int idMax = idFirst + 10;
*wszBuf = 0;
if (hmenu == NULL)
return;
// First delete any previous stationery off this menu
for (UINT i = idFirst; i < (UINT)idMax; i++)
{
// When delete fails, then have gone as far as needed
if (0 == DeleteMenu(hmenu, i, MF_BYCOMMAND))
break;
}
DeleteMenu(hmenu, ID_STATIONERY_SEPARATOR, MF_BYCOMMAND);
// Now figure out what index to start inserting at
cNumIDs = GetMenuItemCount(hmenu) - 1;
while (((UINT)idMore != GetMenuItemID(hmenu, cNumIDs)) && (cNumIDs > 0))
cNumIDs--;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
ValidateList(FALSE);
pEntry = m_pFirst;
while(pEntry)
{
*wszBuf = 0;
HrGetShowNames(pEntry->m_pwszFile, wszBuf, ARRAYSIZE(wszBuf), iIndex);
if(*wszBuf != 0)
{
InsertMenuWrapW(hmenu, (UINT)(cNumIDs+iIndex), MF_BYPOSITION|MF_STRING, idFirst + iIndex, wszBuf);
iIndex++;
fInsertSep = TRUE;
}
pEntry = pEntry->m_pNext;
}
if(fInsertSep)
InsertMenu(hmenu, (UINT)(cNumIDs+iIndex), MF_BYPOSITION | MF_SEPARATOR, ID_STATIONERY_SEPARATOR, NULL);
return;
}
void CStationery::GetStationeryMenu(HMENU *phMenu)
{
LPLISTENTRY pEntry = m_pFirst;
INT iIndex = 0;
WCHAR wszBuf[MAX_PATH];
*wszBuf = 0;
*phMenu = LoadPopupMenu(IDR_NEW_MSG_POPUP);
ValidateList(FALSE);
pEntry = m_pFirst;
while(pEntry)
{
*wszBuf = 0;
HrGetShowNames(pEntry->m_pwszFile, wszBuf, ARRAYSIZE(wszBuf), iIndex);
if(*wszBuf != 0)
{
InsertMenuWrapW(*phMenu, (UINT)iIndex, MF_BYPOSITION | MF_STRING, ID_STATIONERY_RECENT_0 + iIndex, wszBuf);
iIndex++;
}
pEntry = pEntry->m_pNext;
}
if(iIndex > 0)
InsertMenu(*phMenu, (UINT)iIndex, MF_BYPOSITION | MF_SEPARATOR, 0, NULL);
}
HRESULT HrStationeryInit(void)
{
HRESULT hr = S_OK;
if (NULL == g_pStationery)
{
g_pStationery = new CStationery;
if (NULL == g_pStationery)
{
hr = E_OUTOFMEMORY;
goto exit;
}
IF_FAILEXIT(hr = g_pStationery->HrLoadStationeryList());
}
exit:
return hr;
}
void AddStationeryMenu(HMENU hmenu, int idPopup, int idFirst, int idMore)
{
if (idPopup)
{
MENUITEMINFOW mii;
mii.cbSize = sizeof(mii);
mii.fMask = MIIM_SUBMENU;
if (GetMenuItemInfoWrapW(hmenu, idPopup, FALSE, &mii))
hmenu = mii.hSubMenu;
}
if(g_pStationery == NULL)
{
if (FAILED(HrStationeryInit()))
return;
}
#pragma prefast(suppress:11, "noise")
g_pStationery->AddStationeryMenu(hmenu, idFirst, idMore);
}
void GetStationeryMenu(HMENU *phmenu)
{
if(g_pStationery == NULL)
{
if (FAILED(HrStationeryInit()))
return;
}
#pragma prefast(suppress:11, "noise")
g_pStationery->GetStationeryMenu(phmenu);
}
HRESULT HrGetStationeryFileName(INT index, LPWSTR pwszFile)
{
HRESULT hr = S_OK;
if(pwszFile==NULL)
IF_FAILEXIT(hr = E_INVALIDARG);
if(g_pStationery == NULL)
IF_FAILEXIT(hr = HrStationeryInit());
#pragma prefast(disable:11, "noise")
*pwszFile = 0;
g_pStationery->HrGetFileName(index, pwszFile);
#pragma prefast(enable:11, "noise")
if(*pwszFile != 0)
{
if(!fValidFile(pwszFile))
{
g_pStationery->ValidateList(TRUE);
IF_FAILEXIT(hr = E_FAIL);
}
InsertStationeryDir(pwszFile);
}
exit:
return hr;
}
HRESULT HrNewStationery(HWND hwnd, INT id, LPWSTR pwszFile,
BOOL fModal, BOOL fMail, FOLDERID folderID,
BOOL fAddToMRU, DWORD dwSource, IUnknown *pUnkPump,
IMimeMessage *pMsg)
{
INT index = id - ID_STATIONERY_RECENT_0;
WCHAR wszBuf[INTERNET_MAX_URL_LENGTH];
HRESULT hr = S_OK;
*wszBuf=0;
if(g_pStationery == NULL)
IF_FAILEXIT(hr = HrStationeryInit());
if(pwszFile == NULL)
g_pStationery->HrGetFileName(index, wszBuf);
else
StrCpyNW(wszBuf, pwszFile, ARRAYSIZE(wszBuf));
if(*wszBuf == 0)
IF_FAILEXIT(hr = E_FAIL)
if(!fValidFile(wszBuf))
{
g_pStationery->ValidateList(TRUE);
IF_FAILEXIT(hr = HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND));
}
InsertStationeryDir(wszBuf);
// This might pop up a dialog, in which case, error might be valid. Don't traceresult.
// If don't add to MRU, then stationery by default. Therefore, send a signature.
hr = HrSendWebPageDirect(wszBuf, hwnd, fModal, fMail, folderID,
TRUE, pUnkPump, pMsg);
if(fAddToMRU && SUCCEEDED(hr))
// Since this only adds to the MRU, we don't care about error.
HrAddToStationeryMRU(wszBuf);
exit:
ULONG ulErrRsrc;
// At this point, if we canceled, then propagate success up.
if (MAPI_E_USER_CANCEL == hr)
hr = S_OK;
if(FAILED(hr))
{
if( hr == HRESULT_FROM_WIN32(ERROR_FILE_NOT_FOUND) )
{
ulErrRsrc = idsErrStationeryNotFound;
switch (dwSource)
{
case NSS_MRU:
// Remove fromt he MRU if file not found.
HrRemoveFromStationeryMRU(wszBuf);
break;
case NSS_DEFAULT:
// need to reset stationary for user if couldn't find it in the dir
if( !SetDwOption( fMail ? OPT_MAIL_USESTATIONERY : OPT_NEWS_USESTATIONERY, 0, hwnd, 0) )
{
DebugTrace("reset failed\n");
}
break;
}
}
else
{
ulErrRsrc = idsErrNewStationery;
}
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaMail),
MAKEINTRESOURCEW(ulErrRsrc), NULL, MB_OK);
if (!pMsg)
{
// Only contacts passes us pMsg. In that case it handles the failure correctly.
if (FNewMessage(hwnd, fModal, FALSE, !fMail, folderID, pUnkPump))
hr = S_OK;
else
hr = E_FAIL;
}
}
return hr;
}
HRESULT HrAddToStationeryMRU(LPWSTR pwszFile)
{
int index;
HRESULT hr;
if (pwszFile==NULL || *pwszFile==0)
IF_FAILEXIT(hr = E_INVALIDARG);
if (g_pStationery == NULL)
IF_FAILEXIT(hr = HrStationeryInit());
StripStationeryDir(pwszFile);
#pragma prefast(suppress:11, "noise")
hr = g_pStationery->HrFindEntry(pwszFile, &index);
if(FAILED(hr))
hr = g_pStationery->HrInsertEntry(pwszFile);
else
hr = g_pStationery->HrPromoteEntry(index);
exit:
return hr;
}
HRESULT HrRemoveFromStationeryMRU(LPWSTR pwszFile)
{
int index;
HRESULT hr;
if (pwszFile==NULL || *pwszFile==0)
IF_FAILEXIT(hr = E_INVALIDARG);
if (g_pStationery == NULL)
IF_FAILEXIT(hr = HrStationeryInit());
StripStationeryDir(pwszFile);
IF_FAILEXIT(hr = g_pStationery->HrFindEntry(pwszFile, &index));
IF_FAILEXIT(hr = g_pStationery->HrDeleteEntry(index));
exit:
return hr;
}
HRESULT HrGetStationeryPath(LPWSTR pwszPath)
{
HRESULT hr = NOERROR;
DWORD cb, dwType;
LONG lReg=0;
HKEY hkey = 0;
if(pwszPath == NULL)
IF_FAILEXIT(hr = E_INVALIDARG);
if(*s_wszStationeryDir == 0)
{
if (ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE, c_szRegStationery, 0, KEY_QUERY_VALUE, &hkey))
{
cb = sizeof(s_wszStationeryDir);
// Will need to convert this. Won't compile right now.
lReg = RegQueryValueExWrapW(hkey, c_wszValueStationery, 0, &dwType, (LPBYTE)s_wszStationeryDir , &cb);
if (ERROR_SUCCESS!=lReg || cb==0)
IF_FAILEXIT(hr = E_FAIL);
}
if(*s_wszStationeryDir == 0)
IF_FAILEXIT(hr = E_FAIL);
PathRemoveBackslashW(s_wszStationeryDir);
}
Assert(*s_wszStationeryDir);
ExpandEnvironmentStringsWrapW(s_wszStationeryDir, pwszPath, MAX_PATH);
exit:
if (hkey)
RegCloseKey(hkey);
return hr;
}
HRESULT HrGetMoreStationeryFileName(HWND hwnd, LPWSTR pwszFile)
{
OPENFILENAMEW ofn;
WCHAR wszStationeryOpen[MAX_PATH],
wsz[MAX_PATH],
wszDir[MAX_PATH],
wszFile[MAX_PATH];
LPWSTR pwszDir = NULL;
HRESULT hr = S_OK;
*wszStationeryOpen = *wszDir = *wsz = 0;
if(!pwszFile)
return TraceResult(E_INVALIDARG);
ZeroMemory(&ofn, sizeof(ofn));
AthLoadStringW(idsHtmlFileFilter, wsz, ARRAYSIZE(wsz));
ReplaceCharsW(wsz, L'|', L'\0');
wszFile[0] = L'\0';
AthLoadStringW(idsStationeryOpen, wszStationeryOpen, ARRAYSIZE(wszStationeryOpen));
if (!PathIsDirectoryW(g_wszLastStationeryPath))
{
*g_wszLastStationeryPath = 0;
HrGetStationeryPath(g_wszLastStationeryPath);
}
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwnd;
ofn.hInstance = g_hLocRes;
ofn.lpstrFilter = wsz;
ofn.nFilterIndex = 1;
ofn.lpstrFile = wszFile;
ofn.lpstrTitle = wszStationeryOpen;
ofn.nMaxFile = ARRAYSIZE(wszStationeryOpen);
ofn.lpstrInitialDir = g_wszLastStationeryPath;
ofn.lpTemplateName = MAKEINTRESOURCEW(iddMoreStationery);
ofn.lpfnHook = (LPOFNHOOKPROC)MoreStationeryDlgHookProc;
ofn.Flags = OFN_EXPLORER |
OFN_HIDEREADONLY |
OFN_FILEMUSTEXIST |
OFN_NODEREFERENCELINKS|
OFN_ENABLEHOOK |
OFN_ENABLETEMPLATE |
OFN_NOCHANGEDIR;
if(GetOpenFileNameWrapW(&ofn) && *wszFile!=0)
{
// store the file
StrCpyNW(pwszFile, wszFile, MAX_PATH);
// store the last path
*g_wszLastStationeryPath = 0;
StrCpyNW(g_wszLastStationeryPath, ofn.lpstrFile, ARRAYSIZE(g_wszLastStationeryPath));
if (!PathIsDirectoryW(g_wszLastStationeryPath))
PathRemoveFileSpecW(g_wszLastStationeryPath);
}
else
hr = E_FAIL;
return hr;
}
HRESULT HrMoreStationery(HWND hwnd, BOOL fModal, BOOL fMail, FOLDERID folderID, IUnknown *pUnkPump)
{
WCHAR wszFileName[MAX_PATH];
HRESULT hr;
// Might return user cancel
hr = HrGetMoreStationeryFileName(hwnd, wszFileName);
if(SUCCEEDED(hr))
hr = HrNewStationery(hwnd, 0, wszFileName, fModal, fMail, folderID, TRUE, NSS_MORE_DIALOG, pUnkPump, NULL);
return hr;
}
BOOL CALLBACK MoreStationeryDlgHookProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
WORD code;
switch (msg)
{
case WM_COMMAND:
{
code = GET_WM_COMMAND_CMD(wParam, lParam);
switch (GET_WM_COMMAND_ID(wParam, lParam))
{
case IDC_SHOWPREVIEW_CHECK:
if (code == BN_CLICKED)
{
BOOL fChecked;
fChecked = SendMessage(GET_WM_COMMAND_HWND(wParam,lParam), BM_GETCHECK, 0, 0) == BST_CHECKED;
SetDwOption(OPT_NOPREVIEW, !fChecked, NULL, 0);
if (fChecked)
ShowMorePreview(hwnd);
else
ShowBlankPreview(GetDlgItem(hwnd, IDC_MOREPREVIEW));
}
SetFocus(GetDlgItem(GetParent(hwnd), lst1));
return FALSE;
case IDC_SHOWPREVIEW_BUTTON_EDIT:
{
WCHAR wszBuf[MAX_PATH];
TCHAR szBuf[2 * MAX_PATH];
*wszBuf = 0;
if (SendMessageWrapW(GetParent(hwnd), CDM_GETSPEC, (WPARAM)ARRAYSIZE(wszBuf), (LPARAM)wszBuf) && lstrlenW(wszBuf) > 0)
{
// This is a workaround for a bug in SendMessageWrapW. It doesn't wrap ansi strings properly
//Win 9x returns an ANSI string in the wide buffer.
//Need to make it a real wide string
//Bug# 78629
if (VER_PLATFORM_WIN32_WINDOWS == g_OSInfo.dwPlatformId)
{
memcpy(szBuf, wszBuf, 2 * MAX_PATH);
MultiByteToWideChar(CP_ACP, 0, szBuf, MAX_PATH, wszBuf, MAX_PATH);
}
SHELLEXECUTEINFOW sei;
sei.cbSize = sizeof(sei);
sei.fMask = SEE_MASK_UNICODE;
sei.hwnd = hwnd;
sei.lpVerb = c_wszEditCmd;
sei.lpFile = wszBuf;
sei.lpParameters = NULL;
sei.lpDirectory = NULL;
sei.nShow = SW_SHOWNORMAL;
sei.hInstApp = 0;
if(SE_ERR_NOASSOC == (INT_PTR)ShellExecuteExWrapW(&sei))
{
sei.lpVerb = c_wszNotepad;
ShellExecuteExWrapW(&sei);
}
}
else
{
AthMessageBoxW(hwnd, MAKEINTRESOURCEW(idsAthenaMail),
MAKEINTRESOURCEW(idsErrStatEditNoSelection), NULL, MB_OK);
}
return FALSE;
}
case IDC_SHOWPREVIEW_BUTTON_ADD:
{
CStatWiz* pStatWiz = 0;
HWND hDlg = GetParent(hwnd);
LPWSTR pwszFile;
LPSTR pszFile;
pStatWiz = new CStatWiz();
if( !pStatWiz ) return TRUE; // bail if can't create wiz
if (pStatWiz->DoWizard(hwnd) == S_OK)
{
pwszFile = PathFindFileNameW(pStatWiz->m_wszHtmlFileName);
// bobn; Raid 81946; 7/1/99
// CDM_SETCONTROLTEXT is not handled by SendMessageWrapW,
// we have to thunk it ourselves...
if (VER_PLATFORM_WIN32_NT == g_OSInfo.dwPlatformId)
SendMessageW(hDlg, CDM_SETCONTROLTEXT, (WPARAM)edt1, (LPARAM)pwszFile);
else
{
pszFile = PszToANSI(CP_ACP, pwszFile);
if(pszFile)
{
SendMessageA(hDlg, CDM_SETCONTROLTEXT, (WPARAM)edt1, (LPARAM)pszFile);
MemFree(pszFile);
}
}
if( !DwGetOption(OPT_NOPREVIEW) )
{
ShowMorePreview(hwnd);
}
}
ReleaseObj(pStatWiz);
return FALSE;
}
}
}
return TRUE;
case WM_INITDIALOG:
{
TCHAR szBuf[CCHMAX_STRINGRES];
LoadString(g_hLocRes, idsOK, szBuf, sizeof(szBuf));
if (!DwGetOption(OPT_NOPREVIEW))
CheckDlgButton(hwnd, IDC_SHOWPREVIEW_CHECK, BST_CHECKED);
SetWindowText(GetDlgItem(GetParent(hwnd), IDOK), szBuf);
CenterDialog( GetParent(hwnd) );
}
return TRUE;
case WM_NOTIFY:
MoreStationeryNotify(hwnd, (LPOFNOTIFYW)lParam);
return TRUE;
case WM_HELP:
case WM_CONTEXTMENU:
return OnContextHelp(hwnd, msg, wParam, lParam, g_rgStatWizHlp);
}
return FALSE;
}
void ShowBlankPreview(HWND hwnd)
{
SendMessage(hwnd, THM_LOADPAGE, 0, (LPARAM)c_wszBlankHtml);
}
HRESULT ShowPreview(HWND hwnd, LPWSTR pwszFile)
{
GetStationeryFullName(pwszFile);
// Even if the full name fails, will need to clear the thumbprint
SendMessage(hwnd, THM_LOADPAGE, 0, (LPARAM)pwszFile);
return S_OK;
}
HRESULT FillHtmlToFile(LPSTATWIZ pApp, HANDLE hFile, INT idsSample, BOOL fTemp)
{
WCHAR wszImageFile[MAX_PATH];
CHAR szImageFile[MAX_PATH];
if (!hFile || !pApp)
return E_INVALIDARG;
if (*pApp->m_wszBkPictureFileName)
{
WideCharToMultiByte(CP_ACP, 0, pApp->m_wszBkPictureFileName, -1, szImageFile, ARRAYSIZE(szImageFile), NULL, NULL);
MultiByteToWideChar(CP_ACP, 0, szImageFile, -1, wszImageFile, ARRAYSIZE(wszImageFile));
if(StrCmpW(wszImageFile, pApp->m_wszBkPictureFileName))
return(FillHtmlToFileW(pApp, hFile, idsSample, fTemp));
}
return(FillHtmlToFileA(pApp, hFile, idsSample, fTemp));
}
#define PSZ_CB(psz) lstrlen(psz)*sizeof(*psz)
HRESULT FillHtmlToFileA(LPSTATWIZ pApp, HANDLE hFile, INT idsSample, BOOL fTemp)
{
WCHAR wszFileSpec[MAX_PATH];
CHAR szBuf[MAX_PATH],
szFileSpec[MAX_PATH];
LPSTREAM pStm = NULL;
LPSTR pszFontFace = NULL,
pszFontColor = NULL,
pszBkColor = NULL;
HRESULT hr = S_OK;
*szFileSpec = 0;
if (!hFile || !pApp)
IF_FAILEXIT(hr = E_INVALIDARG);
IF_FAILEXIT(hr = MimeOleCreateVirtualStream(&pStm));
IF_FAILEXIT(hr = pStm->Write(c_szHtmlHeadFmt, PSZ_CB(c_szHtmlHeadFmt), 0));
if (*pApp->m_wszFontFace && pApp->m_iFontSize && *pApp->m_wszFontColor)
{
IF_NULLEXIT(pszFontFace = PszToANSI(CP_ACP, pApp->m_wszFontFace));
IF_NULLEXIT(pszFontColor = PszToANSI(CP_ACP, pApp->m_wszFontColor));
wnsprintf(szBuf, ARRAYSIZE(szBuf), c_szFontFmt, pszFontFace, pApp->m_iFontSize, pszFontColor);
IF_FAILEXIT(hr = pStm->Write(szBuf, PSZ_CB(szBuf), 0));
}
if (pApp->m_iLeftMargin > 0)
{
wnsprintf(szBuf, ARRAYSIZE(szBuf), c_szLeftMarginFmt, pApp->m_iLeftMargin);
IF_FAILEXIT(hr = pStm->Write(szBuf, PSZ_CB(szBuf), 0));
}
if (pApp->m_iTopMargin > 0)
{
wnsprintf(szBuf, ARRAYSIZE(szBuf), c_szTopMarginFmt, pApp->m_iTopMargin);
IF_FAILEXIT(hr = pStm->Write(szBuf, PSZ_CB(szBuf), 0));
}
if (pApp->m_fBold)
IF_FAILEXIT(hr = pStm->Write(c_szBold, PSZ_CB(c_szBold), 0));
if (pApp->m_fItalic)
IF_FAILEXIT(hr = pStm->Write(c_szItalic, PSZ_CB(c_szItalic), 0));
wnsprintf(szBuf, ARRAYSIZE(szBuf), c_szBkPosition, c_lppszBkPos[pApp->m_iVertPos][pApp->m_iHorzPos] );
IF_FAILEXIT(hr = pStm->Write(szBuf, PSZ_CB(szBuf), 0 ));
wnsprintf(szBuf, ARRAYSIZE(szBuf), c_szBkRepeat, c_lpszRepeatPos[pApp->m_iTile]);
IF_FAILEXIT(hr = pStm->Write(szBuf, PSZ_CB(szBuf), 0 ));
IF_FAILEXIT(hr = pStm->Write(c_szStyleClose, PSZ_CB(c_szStyleClose), 0));
if (*pApp->m_wszBkPictureFileName)
{
StrCpyNW(wszFileSpec, pApp->m_wszBkPictureFileName, ARRAYSIZE(wszFileSpec));
if (fTemp)
{
GetStationeryFullName(wszFileSpec);
}
else
{
PathStripPathW(wszFileSpec);
}
WideCharToMultiByte(CP_ACP, 0, wszFileSpec, -1, szFileSpec, MAX_PATH, NULL, NULL);
if (*szFileSpec)
{
wnsprintf(szBuf, ARRAYSIZE(szBuf), c_szBodyFmt, c_szBkPicture, szFileSpec);
IF_FAILEXIT(hr = pStm->Write(szBuf, PSZ_CB(szBuf), 0));
}
}
if (*pApp->m_wszBkColor)
{
IF_NULLEXIT(pszBkColor = PszToANSI(CP_ACP, pApp->m_wszBkColor));
wnsprintf(szBuf, ARRAYSIZE(szBuf), c_szBodyFmt, c_szBkColor, pszBkColor);
IF_FAILEXIT(hr = pStm->Write(szBuf, PSZ_CB(szBuf), 0));
}
if (idsSample)
{
AthLoadString(idsSample, szBuf, ARRAYSIZE(szBuf));
for (int i=0; i<50; i++)
IF_FAILEXIT(hr = pStm->Write(szBuf, PSZ_CB(szBuf), 0));
}
IF_FAILEXIT(hr = pStm->Write(c_szHtmlClose, PSZ_CB(c_szHtmlClose), 0));
IF_FAILEXIT(hr = HrRewindStream(pStm));
IF_FAILEXIT(hr = WriteStreamToFileHandle(pStm, hFile, NULL));
IF_FAILEXIT(hr = (FlushFileBuffers(hFile)?S_OK:E_FAIL));
exit:
MemFree(pszFontFace);
MemFree(pszFontColor);
MemFree(pszBkColor);
ReleaseObj(pStm);
return hr;
}
#define PWSZ_CB(pwsz) lstrlenW(pwsz)*sizeof(*pwsz)
HRESULT FillHtmlToFileW(LPSTATWIZ pApp, HANDLE hFile, INT idsSample, BOOL fTemp)
{
WCHAR wszBuf[MAX_PATH],
wszFileSpec[MAX_PATH];
LPSTREAM pStm = NULL;
BYTE bUniMark = 0xFF;
HRESULT hr = S_OK;
*wszFileSpec = 0;
if (!hFile || !pApp)
IF_FAILEXIT(hr = E_INVALIDARG);
IF_FAILEXIT(hr = MimeOleCreateVirtualStream(&pStm));
// Write out the BOM
IF_FAILEXIT(hr = pStm->Write(&bUniMark, sizeof(bUniMark), NULL));
bUniMark = 0xFE;
IF_FAILEXIT(hr = pStm->Write(&bUniMark, sizeof(bUniMark), NULL));
IF_FAILEXIT(hr = pStm->Write(c_wszHtmlHeadFmt, PWSZ_CB(c_wszHtmlHeadFmt), 0));
if (*pApp->m_wszFontFace && pApp->m_iFontSize && *pApp->m_wszFontColor)
{
wnsprintfW(wszBuf, ARRAYSIZE(wszBuf), c_wszFontFmt, pApp->m_wszFontFace, pApp->m_iFontSize, pApp->m_wszFontColor);
IF_FAILEXIT(hr = pStm->Write(wszBuf, PWSZ_CB(wszBuf), 0));
}
if (pApp->m_iLeftMargin > 0)
{
wnsprintfW(wszBuf, ARRAYSIZE(wszBuf), c_wszLeftMarginFmt, pApp->m_iLeftMargin);
IF_FAILEXIT(hr = pStm->Write(wszBuf, PWSZ_CB(wszBuf), 0));
}
if (pApp->m_iTopMargin > 0)
{
wnsprintfW(wszBuf, ARRAYSIZE(wszBuf), c_wszTopMarginFmt, pApp->m_iTopMargin);
IF_FAILEXIT(hr = pStm->Write(wszBuf, PWSZ_CB(wszBuf), 0));
}
if (pApp->m_fBold)
IF_FAILEXIT(hr = pStm->Write(c_wszBold, PWSZ_CB(c_wszBold), 0));
if (pApp->m_fItalic)
IF_FAILEXIT(hr = pStm->Write(c_wszItalic, PWSZ_CB(c_wszItalic), 0));
wnsprintfW(wszBuf, ARRAYSIZE(wszBuf), c_wszBkPosition, c_lppwszBkPos[pApp->m_iVertPos][pApp->m_iHorzPos] );
IF_FAILEXIT(hr = pStm->Write(wszBuf, PWSZ_CB(wszBuf), 0 ));
wnsprintfW(wszBuf, ARRAYSIZE(wszBuf), c_wszBkRepeat, c_lpwszRepeatPos[pApp->m_iTile]);
IF_FAILEXIT(hr = pStm->Write(wszBuf, PWSZ_CB(wszBuf), 0 ));
IF_FAILEXIT(hr = pStm->Write(c_wszStyleClose, PWSZ_CB(c_wszStyleClose), 0));
if (*pApp->m_wszBkPictureFileName)
{
StrCpyNW(wszFileSpec, pApp->m_wszBkPictureFileName, ARRAYSIZE(wszFileSpec));
if (fTemp)
{
GetStationeryFullName(wszFileSpec);
}
else
{
PathStripPathW(wszFileSpec);
}
if (*wszFileSpec)
{
wnsprintfW(wszBuf, ARRAYSIZE(wszBuf), c_wszBodyFmt, c_wszBkPicture, wszFileSpec);
IF_FAILEXIT(hr = pStm->Write(wszBuf, PWSZ_CB(wszBuf), 0));
}
}
if (*pApp->m_wszBkColor)
{
wnsprintfW(wszBuf, ARRAYSIZE(wszBuf), c_wszBodyFmt, c_wszBkColor, pApp->m_wszBkColor);
IF_FAILEXIT(hr = pStm->Write(wszBuf, PWSZ_CB(wszBuf), 0));
}
if (idsSample)
{
AthLoadStringW(idsSample, wszBuf, ARRAYSIZE(wszBuf));
for (int i=0; i<50; i++)
IF_FAILEXIT(hr = pStm->Write(wszBuf, PWSZ_CB(wszBuf), 0));
}
IF_FAILEXIT(hr = pStm->Write(c_wszHtmlClose, PWSZ_CB(c_wszHtmlClose), 0));
IF_FAILEXIT(hr = HrRewindStream(pStm));
IF_FAILEXIT(hr = WriteStreamToFileHandle(pStm, hFile, NULL));
IF_FAILEXIT(hr = (FlushFileBuffers(hFile)?S_OK:E_FAIL));
exit:
ReleaseObj(pStm);
return hr;
}
HRESULT ShowPreview(HWND hwnd, LPSTATWIZ pApp, INT idsSample)
{
WCHAR wszBuf[MAX_PATH];
HRESULT hr;
LPSTREAM pStm = NULL;
LPSTR pszTempFile = NULL;
LPWSTR pwszTempFile = NULL;
HANDLE hFile=0;
*wszBuf = 0;
if (!hwnd || !pApp)
IF_FAILEXIT(hr = E_INVALIDARG);
IF_FAILEXIT(hr = CreateTempFile(c_szTempFileName, c_szHtmlExtension, &pszTempFile, &hFile));
IF_FAILEXIT(hr = FillHtmlToFile(pApp, hFile, idsSample, TRUE));
IF_NULLEXIT(pwszTempFile = PszToUnicode(CP_ACP, pszTempFile));
SendMessage(hwnd, THM_LOADPAGE, 0, (LPARAM)pwszTempFile);
exit:
if (hFile)
CloseHandle(hFile);
if (pszTempFile)
DeleteFile(pszTempFile);
MemFree(pszTempFile);
MemFree(pwszTempFile);
return hr;
}
HRESULT ShowMorePreview(HWND hwnd)
{
HRESULT hr = S_OK;
WCHAR wszFile[MAX_PATH];
TCHAR szFile[2 * MAX_PATH];
*wszFile = 0;
// Get the path of the selected file.
if (SendMessageWrapW(GetParent(hwnd), CDM_GETFILEPATH, (WPARAM)ARRAYSIZE(wszFile), (LPARAM)(LPWSTR)wszFile) &&
*wszFile!=0)
{
//Work around for a bug in SendMessageWrapW
//Win 9x returns an ANSI string in the wide buffer.
//Need to make it a real wide string
//Bug# 78619
if (VER_PLATFORM_WIN32_WINDOWS == g_OSInfo.dwPlatformId)
{
memcpy(szFile, wszFile, 2 * MAX_PATH);
MultiByteToWideChar(CP_ACP, 0, szFile, MAX_PATH, wszFile, MAX_PATH);
}
hr = ShowPreview(GetDlgItem(hwnd, IDC_MOREPREVIEW), wszFile);
}
return hr;
}
BOOL PASCAL MoreStationeryNotify(HWND hDlg, LPOFNOTIFYW pofn)
{
if (CDN_SELCHANGE == pofn->hdr.code)
{
if (IsDlgButtonChecked(hDlg, IDC_SHOWPREVIEW_CHECK))
ShowMorePreview(hDlg);
}
return TRUE;
}
BOOL FHtmlFile(LPWSTR pwszFile)
{
LPWSTR pwszExt = PathFindExtensionW(pwszFile);
if (pwszExt && (StrStrIW(pwszExt, L".htm") || StrStrIW(pwszExt, L".html")))
return TRUE;
else
return FALSE;
}
VOID InsertStationeryDir(LPWSTR pwszPicture)
{
WCHAR wszDir[MAX_PATH],
wszCopy[MAX_PATH];
LPWSTR pwszT1 = NULL,
pwszT2 = NULL;
*wszDir = 0;
*wszCopy = 0;
if(pwszPicture == NULL || lstrlenW(pwszPicture)==0)
return;
pwszT1 = StrStrIW(pwszPicture, L"\\"); //private drive
pwszT2 = StrStrIW(pwszPicture, L"/"); //URLs
if(pwszT1==NULL && pwszT2==NULL) // files in background directory.
{
if (SUCCEEDED(HrGetStationeryPath(wszDir)))
{
StrCpyNW(wszCopy, pwszPicture, ARRAYSIZE(wszCopy));
wnsprintfW(pwszPicture, MAX_PATH, L"%s\\%s", wszDir, wszCopy);
}
}
return;
}
DWORD GetShortPathNameWrapW(LPCWSTR pwszLongPath, LPWSTR pwszShortPath, DWORD cchBuffer)
{
CHAR szShortPath[MAX_PATH*2]; // Each Unicode char might go multibyte
LPSTR pszLongPath = NULL;
DWORD cch = 0,
cch2 = 0;
Assert(pwszLongPath);
Assert(pwszShortPath);
pwszShortPath[0] = L'\0';
if (VER_PLATFORM_WIN32_NT == g_OSInfo.dwPlatformId)
return(GetShortPathNameW(pwszLongPath, pwszShortPath, cchBuffer));
pszLongPath = PszToANSI(CP_ACP, pwszLongPath);
if (pszLongPath)
{
cch2 = GetShortPathName(pszLongPath, szShortPath, ARRAYSIZE(szShortPath));
if (cch2)
cch2 = MultiByteToWideChar(CP_ACP, 0, szShortPath, cch2+1, pwszShortPath, cchBuffer);
if (cch2)
cch = cch2 - 1;
MemFree(pszLongPath);
}
return cch;
}
HRESULT StripStationeryDir(LPWSTR pwszPicture)
{
WCHAR wszDir[MAX_PATH],
wszPicture[MAX_PATH],
wszPicturePath[MAX_PATH],
wszShortPath[MAX_PATH] = L"",
wszShortDir[MAX_PATH] = L"";
HRESULT hr = E_FAIL;
DWORD cch;
*wszDir = *wszPicture = *wszPicturePath = 0;
if (pwszPicture==NULL)
IF_FAILEXIT(hr = E_INVALIDARG);
IF_FAILEXIT(hr = HrGetStationeryPath(wszDir));
StrCpyNW(wszPicturePath, pwszPicture, ARRAYSIZE(wszPicturePath));
PathRemoveFileSpecW(wszPicturePath);
PathRemoveBackslashW(wszPicturePath);
if (0 == StrCmpIW(wszDir, wszPicturePath))
PathStripPathW(pwszPicture);
else
{
// Convert the Picture Path to the short name as
// it could be in the registry that way...
if((cch = GetShortPathNameWrapW(wszDir, wszShortDir, ARRAYSIZE(wszShortDir)))==0)
{
hr = E_FAIL;
goto exit;
}
if((cch = GetShortPathNameWrapW(wszPicturePath, wszShortPath, ARRAYSIZE(wszShortPath)))==0)
{
hr = E_FAIL;
goto exit;
}
if (0 == StrCmpIW(wszShortDir, wszShortPath))
PathStripPathW(pwszPicture);
}
exit:
return hr;
}
BOOL GetStationeryFullName(LPWSTR pwszName)
{
WCHAR wszBuf[MAX_PATH];
DWORD dwAttributes;
HRESULT hr = S_OK;
*wszBuf = 0;
if (pwszName==NULL || *pwszName==0)
IF_FAILEXIT(hr = E_INVALIDARG);
InsertStationeryDir(pwszName);
StrCpyNW(wszBuf, pwszName, ARRAYSIZE(wszBuf));
if (!FHtmlFile(wszBuf))
PathAddExtensionW(wszBuf, L".htm");
if (!PathFileExistsW(wszBuf))
{
StrCpyNW(wszBuf, pwszName, ARRAYSIZE(wszBuf));
if (!FHtmlFile(wszBuf))
PathAddExtensionW(wszBuf, L".html");
if (!PathFileExistsW(wszBuf))
{
*pwszName = 0; //this file does not exist.
IF_FAILEXIT(hr = E_FAIL);
}
}
StrCpyNW(pwszName, wszBuf, MAX_PATH);
exit:
return SUCCEEDED(hr);
}
BOOL IsValidCreateFileName(LPWSTR pwszFile)
{
BOOL fRet = TRUE;
WCHAR wszBuf[MAX_PATH];
HANDLE hFile;
*wszBuf = 0;
StrCpyNW(wszBuf, pwszFile, ARRAYSIZE(wszBuf));
if (!FHtmlFile(wszBuf))
PathAddExtensionW(wszBuf, L".htm");
InsertStationeryDir(wszBuf);
if (!PathFileExistsW(wszBuf))
{
hFile = CreateFileWrapW(wszBuf, GENERIC_READ|GENERIC_WRITE, FILE_SHARE_READ|FILE_SHARE_WRITE, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_ARCHIVE, NULL);
if (hFile != INVALID_HANDLE_VALUE)
{
CloseHandle(hFile);
DeleteFileWrapW(wszBuf);
StrCpyNW(pwszFile, wszBuf, MAX_PATH);
fRet = FALSE;
}
}
return fRet;
}
LRESULT StationeryListBox_AddString(HWND hwndList, LPWSTR pwszFileName)
{
LRESULT lr=CB_ERR;
WCHAR wszBuf[MAX_PATH];
HDC hdc;
PAINTSTRUCT ps;
SIZE rSize;
HFONT hfontOld, hfont;
*wszBuf = 0;
if(pwszFileName==NULL || *pwszFileName==0)
return lr;
StrCpyNW(wszBuf, pwszFileName, ARRAYSIZE(wszBuf));
StripStationeryDir(wszBuf);
PathRemoveExtensionW(wszBuf);
// If cannot find it
if (SendMessageWrapW(hwndList, LB_FINDSTRINGEXACT, 0, (LPARAM)wszBuf))
{
hdc = GetDC(hwndList);
hfont = (HFONT) SendMessage(hwndList, WM_GETFONT, 0, 0);
hfontOld = (HFONT) SelectObject(hdc, hfont);
GetTextExtentPoint32AthW(hdc, wszBuf, lstrlenW(wszBuf), &rSize, NOFLAGS);
SelectObject(hdc, hfontOld);
ReleaseDC(hwndList, hdc);
if((rSize.cx+10) > ListBox_GetHorizontalExtent(hwndList))
ListBox_SetHorizontalExtent(hwndList, rSize.cx+10);
lr = SendMessageWrapW(hwndList, LB_ADDSTRING, 0, (LPARAM)wszBuf);
}
return lr;
}
LRESULT StationeryListBox_SelectString(HWND hwndList, LPWSTR pwszFileName)
{
LRESULT lr=CB_ERR;
WCHAR wszBuf[MAX_PATH];
*wszBuf = 0;
if (pwszFileName != NULL && *pwszFileName != 0)
{
StrCpyNW(wszBuf, pwszFileName, ARRAYSIZE(wszBuf));
StripStationeryDir(wszBuf);
PathRemoveExtensionW(wszBuf);
lr = SendMessageWrapW(hwndList, LB_FINDSTRINGEXACT, 0, (LPARAM)wszBuf);
}
if (lr < 0)
lr = 0;
ListBox_SetCurSel(hwndList, lr);
return lr;
}
LRESULT StationeryComboBox_SelectString(HWND hwndCombo, LPWSTR pwszFileName)
{
LRESULT lr=CB_ERR;
WCHAR wszBuf[MAX_PATH];
*wszBuf = 0;
if (pwszFileName != NULL && *pwszFileName != 0)
{
StrCpyNW(wszBuf, pwszFileName, ARRAYSIZE(wszBuf));
StripStationeryDir(wszBuf);
lr = SendMessageWrapW(hwndCombo, LB_FINDSTRINGEXACT, 0, (LPARAM)wszBuf);
}
if (lr < 0)
lr = 0;
ComboBox_SetCurSel(hwndCombo, lr);
return lr;
}
HRESULT HrLoadStationery(HWND hwndList, LPWSTR pwszStationery)
{
HRESULT hr = NOERROR;
LPWSTR pwszFiles = NULL,
pwszT = NULL,
pwsz = NULL;
LRESULT lr=0;
WCHAR wszDir[MAX_PATH];
DWORD dw, dwType=0, cb=0;
HKEY hkey=NULL;
INT i;
*wszDir = 0;
ListBox_ResetContent(hwndList);
IF_FAILEXIT(hr = HrGetStationeryPath(wszDir))
for(i = 0; i < (ARRAYSIZE(c_rgpwszHTMLExtensions)); i++)
{
if(pwszFiles = Util_EnumFiles(wszDir, c_rgpwszHTMLExtensions[i]))
{
pwszT = pwszFiles;
while (*pwszT)
{
lr = StationeryListBox_AddString(hwndList, pwszT);
pwszT += (lstrlenW(pwszT) + 1);
}
}
SafeMemFree(pwszFiles);
}
StationeryListBox_AddString(hwndList, pwszStationery);
exit:
StationeryListBox_SelectString(hwndList, pwszStationery);
return hr;
}
HRESULT HrBrowsePicture(HWND hwndParent, HWND hwndCombo)
{
OPENFILENAMEW ofn;
WCHAR wszOpenFileName[MAX_PATH],
wsz[MAX_PATH],
wszDir[MAX_PATH],
wszTitle[MAX_PATH];
LPWSTR pwszDir = NULL;
HRESULT hr;
*wszOpenFileName = *wsz = *wszDir = *wszTitle = 0;
ZeroMemory(&ofn, sizeof(ofn));
AthLoadStringW(idsImageFileFilter, wsz, ARRAYSIZE(wsz));
ReplaceCharsW(wsz, L'|', L'\0');
AthLoadStringW(idsPictureTitle, wszTitle, ARRAYSIZE(wszTitle));
hr = HrGetStationeryPath(wszDir);
if(SUCCEEDED(hr))
pwszDir = wszDir;
ofn.lStructSize = sizeof(ofn);
ofn.hwndOwner = hwndParent;
ofn.hInstance = g_hLocRes;
ofn.lpstrFilter = wsz;
ofn.nFilterIndex = 1;
ofn.lpstrFile = wszOpenFileName;
ofn.nMaxFile = MAX_PATH;
ofn.lpstrInitialDir = pwszDir;
ofn.lpstrTitle = wszTitle;
ofn.Flags = OFN_EXPLORER |
OFN_HIDEREADONLY |
OFN_FILEMUSTEXIST |
OFN_NODEREFERENCELINKS|
OFN_NOCHANGEDIR;
if(GetOpenFileNameWrapW(&ofn))
PictureComboBox_AddString(hwndCombo, wszOpenFileName);
return hr;
}
// lpszPicture is the default picture name,
HRESULT HrFillStationeryCombo(HWND hwndCombo, BOOL fBackGround, LPWSTR pwszPicture)
{
HRESULT hr = NOERROR;
LPWSTR pwszFiles = NULL,
pwszT = NULL,
pwsz = NULL;
const LPWSTR *pwszExtension = NULL;
LRESULT lr=0;
WCHAR wszDir[MAX_PATH];
DWORD dw,
dwType=0,
cb = 0;
HKEY hkey=NULL;
INT i, size;
*wszDir = 0;
IF_FAILEXIT(hr = HrGetStationeryPath(wszDir));
if (fBackGround)
{
pwszExtension = c_wszPictureExtensions;
size = ARRAYSIZE(c_wszPictureExtensions);
}
else
{
pwszExtension = c_rgpwszHTMLExtensions;
size = ARRAYSIZE(c_rgpwszHTMLExtensions);
}
for(i = 0; i < size; i++)
{
if(pwszFiles = Util_EnumFiles(wszDir, pwszExtension[i]))
{
pwszT = pwszFiles;
while (*pwszT)
{
lr = SendMessageWrapW(hwndCombo, CB_ADDSTRING, 0, (LPARAM)pwszT);
if (lr == CB_ERR || lr == CB_ERRSPACE)
break;
pwszT += (lstrlenW(pwszT) + 1);
}
}
SafeMemFree(pwszFiles);
if(lr == CB_ERR || lr == CB_ERRSPACE)
break;
}
exit:
// add the default picture name.
if (pwszPicture)
PictureComboBox_AddString(hwndCombo, pwszPicture);
return hr;
}
// add default picture name to the background picture combobox.
LRESULT PictureComboBox_AddString(HWND hwndCombo, LPWSTR pwszPicture)
{
LRESULT lr=CB_ERR;
if(pwszPicture==NULL || *pwszPicture==0 || !IsValidFileName(pwszPicture))
return lr;
StripStationeryDir(pwszPicture);
if (SendMessageWrapW(hwndCombo, CB_FINDSTRINGEXACT, (WPARAM)0, (LPARAM)pwszPicture) < 0)
{
lr = SendMessageWrapW(hwndCombo, CB_ADDSTRING, 0, (LPARAM)pwszPicture);
if(lr==CB_ERR || lr==CB_ERRSPACE)
return lr;
}
lr = SendMessageWrapW(hwndCombo, CB_SELECTSTRING, (WPARAM)-1, (LPARAM)pwszPicture);
return lr;
}
BOOL IsValidFileName(LPWSTR pwszFile)
{
BOOL fRet = TRUE;
WCHAR wszBuf[INTERNET_MAX_URL_LENGTH];
*wszBuf = 0;
if(pwszFile == NULL || *pwszFile == 0)
{
fRet = FALSE;
goto exit;
}
StrCpyNW(wszBuf, pwszFile, ARRAYSIZE(wszBuf));
InsertStationeryDir(wszBuf);
if(!PathIsURLW(wszBuf))
{
if(!PathFileExistsW(wszBuf))
{
fRet = FALSE;
goto exit;
}
}
exit:
return fRet;
}
// Assumes that pwszName is of at least MAX_PATH chars
HRESULT GetDefaultStationeryName(BOOL fMail, LPWSTR pwszName)
{
DWORD fConverted = TRUE;
CHAR szName[MAX_PATH];
*pwszName = 0;
*szName = 0;
fConverted = DwGetOption(fMail?OPT_MAIL_STATCONVERTED:OPT_NEWS_STATCONVERTED);
if (!fConverted)
{
fConverted = TRUE;
GetOption(fMail?OPT_MAIL_STATIONERYNAME:OPT_NEWS_STATIONERYNAME, szName, sizeof(szName));
MultiByteToWideChar(CP_ACP, 0, szName, -1, pwszName, MAX_PATH);
SetDefaultStationeryName(fMail, pwszName);
}
else
GetOption(fMail?OPT_MAIL_STATIONERYNAMEW:OPT_NEWS_STATIONERYNAMEW, pwszName, MAX_PATH*sizeof(WCHAR));
return (0 == *pwszName) ? E_FAIL : S_OK;
}
HRESULT SetDefaultStationeryName(BOOL fMail, LPWSTR pwszName)
{
DWORD fConverted = TRUE;
SetOption(fMail?OPT_MAIL_STATIONERYNAMEW:OPT_NEWS_STATIONERYNAMEW, pwszName, (lstrlenW(pwszName)+1)*sizeof(WCHAR), NULL, 0);
SetDwOption(fMail?OPT_MAIL_STATCONVERTED:OPT_NEWS_STATCONVERTED, fConverted, NULL, 0);
return S_OK;
}