// ================================================================================= // 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 #include #include "regutil.h" #include "menuutil.h" #include "thumb.h" #include "optres.h" #include #include "url.h" #include #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"\r\n\r\n\r\n\r\n"; const static WCHAR c_wszBodyFmt[] = L"\r\n"; const static WCHAR c_wszHtmlClose[] = L"\r\n\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[] = "\r\n\r\n\r\n\r\n"; const static CHAR c_szBodyFmt[] = "\r\n"; const static CHAR c_szHtmlClose[] = "\r\n\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; im_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; }