|
|
/* Copyright 1996 Microsoft */
#include "priv.h"
#ifdef DEBUG
#define ENTERPROC EnterProc
#define EXITPROC ExitProc
void EnterProc(DWORD dwTraceLevel, LPTSTR szFmt, ...); void ExitProc(DWORD dwTraceLevel, LPTSTR szFmt, ...);
extern DWORD g_dwIEDDETrace;
#else
#pragma warning(disable:4002)
#ifndef UNIX
#ifndef CCOVER
#define ENTERPROC()
#define EXITPROC()
#else //CCOVER
// these are needed because of a bug in cl.exe which causes
// compilation problems with #pragma when a program is preprocessed
// and compiled separately
#define ENTERPROC 1 ? (void) 0 : (void)
#define EXITPROC 1 ? (void) 0 : (void)
#endif // CCOVER
#else
#define ENTERPROC EnterProc
#define EXITPROC ExitProc
inline void EnterProc(DWORD dwTraceLevel, LPTSTR szFmt, ...){} inline void ExitProc(DWORD dwTraceLevel, LPTSTR szFmt, ...){} #endif
#endif
//
// Forward reference.
//
class CIEDDEThread;
//
// Stored in _hdsaWinitem
//
typedef struct _tagWinItem { DWORD dwWindowID; // Synthetic window ID exposed in IEDDE interfaces
HWND hwnd; // Actual hwnd of browser window
DWORD dwThreadID; // ThreadID for this browser window
CIEDDEThread *pidt; // Thread specific data and methods
} WINITEM;
//
// Stored in _hdsaProtocolHandler
//
typedef struct _tagProtocolReg { LPTSTR pszProtocol; LPTSTR pszServer; } PROTOCOLREG;
#define TEN_SECONDS (10 * 1000)
#define DXA_GROWTH_AMOUNT (10)
#ifndef UNIX
#define IEXPLORE_STR "IEXPLORE"
#else
#define IEXPLORE_STR "iexplorer"
#endif
static const TCHAR c_szIExplore[] = TEXT(IEXPLORE_STR); static const TCHAR c_szReturn[] = TEXT("Return"); static const TCHAR c_szWWWOpenURL[] = TEXT("WWW_OpenURL"); static const TCHAR c_szWWWUrlEcho[] = TEXT("WWW_URLEcho");
typedef struct _tagDDETHREADINFO { DWORD dwDDEInst; HSZ hszService; HSZ hszReturn; HDDEDATA hddNameService; } DDETHREADINFO;
class CIEDDEThread { public: CIEDDEThread() { }; ~CIEDDEThread() { };
void GetDdeThreadInfo(DDETHREADINFO *pdti) { *pdti = _dti; } void SetDdeThreadInfo(DDETHREADINFO *pdti) { _dti = *pdti; } HDDEDATA OnRequestPoke(HSZ hszTopic, HSZ hszParams); HDDEDATA OnExecute(HSZ hszTopic, HDDEDATA hddParams);
HDDEDATA CallTopic(DWORD dwType, LPCTSTR pszTopic, LPTSTR pszParams);
protected: DDETHREADINFO _dti;
HDDEDATA DoNavigate(LPTSTR pszLocation, HWND hwnd, BOOL bLaunchNewWindow); BOOL MakeQuotedString(LPCTSTR pszInput, LPTSTR pszOutput, int cchOutput); HDDEDATA CreateReturnObject(LPVOID p, DWORD cb); HDDEDATA CreateReturnStringObject(LPTSTR pszReturnString, DWORD cch);
BOOL ParseString(LPTSTR *ppsz, LPTSTR *ppszString); BOOL ParseQString(LPTSTR *ppsz, LPTSTR *ppszString); BOOL ParseNumber(LPTSTR *ppsz, DWORD *pdw); BOOL ParseWinitem(LPTSTR *ppsz, WINITEM *pwi);
HDDEDATA WWW_GetWindowInfo(LPTSTR pszParams); HDDEDATA WWW_OpenURL(LPTSTR pszParams); HDDEDATA WWW_OpenURLNewWindow(LPTSTR pszParams); HDDEDATA WWW_ShowFile(LPTSTR pszParams); HDDEDATA WWW_Activate(LPTSTR pszParams); HDDEDATA WWW_Exit(LPTSTR pszParams); HDDEDATA WWW_RegisterURLEcho(LPTSTR pszParams); HDDEDATA WWW_UnregisterURLEcho(LPTSTR pszParams); HDDEDATA WWW_RegisterProtocol(LPTSTR pszParams); HDDEDATA WWW_UnregisterProtocol(LPTSTR pszParams); HDDEDATA WWW_ListWindows(LPTSTR pszParams); };
class CIEDDE { public: CIEDDE() { }; ~CIEDDE() { };
BOOL IsAutomationReady(void) { return _fAutomationReady; } BOOL GetWinitemFromWindowID(DWORD dwWindowID, WINITEM *pwi); BOOL GetWinitemFromHwnd(HWND hwnd, WINITEM *pwi); BOOL AddUrlEcho(LPCTSTR pszUrlEcho); BOOL RemoveUrlEcho(LPCTSTR pszUrlEcho); BOOL AddProtocolHandler(LPCTSTR pszServer, LPCTSTR pszProtocol); BOOL RemoveProtocolHandler(LPCTSTR pszServer, LPCTSTR pszProtocol); HDSA GetHdsaWinitem(void) { return _hdsaWinitem; } static HDDEDATA DdeCallback(UINT dwType, UINT dwFmt, HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hdd, DWORD dwData1, DWORD dwData2); void EnterCrit(void) { ASSERT(_fCSInitialized); EnterCriticalSection(&_csIEDDE); } void LeaveCrit(void) { ASSERT(_fCSInitialized); LeaveCriticalSection(&_csIEDDE); } void SetDelayedExecute(LPCTSTR pszTopic, LPCTSTR pszParams); void RunDelayedExecute(); protected: BOOL _fAutomationReady; HDSA _hdsaWinitem; HDSA _hdsaProtocolHandler; HDPA _hdpaUrlEcho; BOOL _fCSInitialized; CRITICAL_SECTION _csIEDDE; DWORD _dwThreadID; LPTSTR _pszTopic; LPTSTR _pszParams;
HDDEDATA _SendDDEMessageHsz(DWORD dwDDEInst, HSZ hszApp, HSZ hszTopic, HSZ hszMessage, UINT wType); HDDEDATA _SendDDEMessageSz(DWORD dwDDEInst, LPCTSTR pszApp, LPCTSTR pszTopic, LPCTSTR pszMessage, UINT wType);
static int _DestroyProtocol(LPVOID p1, LPVOID p2); static int _DestroyUrlEcho(LPVOID p1, LPVOID p2); static int _DestroyWinitem(LPVOID p1, LPVOID p2);
BOOL _GetWinitemFromThread(DWORD dwThreadID, WINITEM *pwi); BOOL _GetDtiFromThread(DWORD dwThreadID, DDETHREADINFO *pdti);
BOOL _CreateDdeThreadInfo(DDETHREADINFO *pdti); void _DestroyDdeThreadInfo(DDETHREADINFO *pdti); BOOL _AddWinitem(WINITEM *pwi); BOOL _UpdateWinitem(WINITEM *pwi); BOOL _DeleteWinitemByHwnd(HWND hwnd, WINITEM *pwi);
BOOL _Initialize(void); void _Uninitialize(void); void _AutomationStarted(void); HRESULT _BeforeNavigate(LPCTSTR pszURL, BOOL *pfProcessed); HRESULT _AfterNavigate(LPCTSTR pszURL, HWND hwnd); BOOL _NewWindow(HWND hwnd); BOOL _WindowDestroyed(HWND hwnd);
friend BOOL IEDDE_Initialize(void); friend void IEDDE_Uninitialize(void); friend void IEDDE_AutomationStarted(void); friend HRESULT IEDDE_BeforeNavigate(LPCWSTR pwszURL, BOOL *pfProcessed); friend HRESULT IEDDE_AfterNavigate(LPCWSTR pwszURL, HWND hwnd); friend BOOL IEDDE_NewWindow(HWND hwnd); friend BOOL IEDDE_WindowDestroyed(HWND hwnd); }; CIEDDE *g_pIEDDE = NULL;
#define ENTER_IEDDE_CRIT g_pIEDDE->EnterCrit()
#define LEAVE_IEDDE_CRIT g_pIEDDE->LeaveCrit()
//
// There is one CIEDDEThread object per browser window.
// Its private data consists of DDE handles, which are
// necessarily valid only in the thread that created them.
//
// Its methods consist of three broad categories:
// the parser
// the dispatcher
// one handler for each DDE topic
//
//
// CreateReturnObject - creates a dde data item.
//
#define CREATE_HDD(x) CreateReturnObject(&x, SIZEOF(x))
HDDEDATA CIEDDEThread::CreateReturnObject(LPVOID p, DWORD cb) { HDDEDATA hddRet;
ENTERPROC(2, TEXT("CreateReturnObject(p=%08X,cb=%d)"), p, cb);
hddRet = DdeCreateDataHandle(_dti.dwDDEInst, (BYTE *)p, cb, 0, _dti.hszReturn, CF_TEXT, 0);
if (hddRet == 0) { TraceMsg(TF_WARNING, "IEDDE: Could not create return object"); }
EXITPROC(2, TEXT("CreateReturnObject=%08X"), hddRet); return hddRet; }
HDDEDATA CIEDDEThread::CreateReturnStringObject(LPTSTR pszReturnString, DWORD cch) { HDDEDATA hddRet = 0;
ENTERPROC(2, TEXT("CreateReturnStringObject(p=%s,cb=%d)"), pszReturnString, cch);
//
// REVIEW I thought specifying CF_UNICODETEXT should have worked, but...
// it didn't, so always return ANSI string as out string params
// - julianj
//
LPSTR pszAnsiBuf = (LPSTR)LocalAlloc(LPTR, cch+1); if (pszAnsiBuf) { SHUnicodeToAnsi(pszReturnString, pszAnsiBuf, cch+1); hddRet = DdeCreateDataHandle(_dti.dwDDEInst, (BYTE *)pszAnsiBuf, (cch+1), 0, _dti.hszReturn, CF_TEXT, 0); LocalFree(pszAnsiBuf); pszAnsiBuf = NULL; } if (hddRet == 0) { TraceMsg(TF_WARNING, "IEDDE: Could not create return object"); }
EXITPROC(2, TEXT("CreateReturnObject=%08X"), hddRet); return hddRet; }
//
// OnRequestPoke - handle XTYP_REQUEST and XTYP_POKE
//
HDDEDATA CIEDDEThread::OnRequestPoke(HSZ hszTopic, HSZ hszParams) { HDDEDATA hddRet = 0; ENTERPROC(2, TEXT("OnRequestPoke(hszTopic=%08X,hszParams=%08X)"), hszTopic, hszParams);
TCHAR szTopic[100]; TCHAR szParams[1000];
if (DdeQueryString(_dti.dwDDEInst, hszTopic, szTopic, ARRAYSIZE(szTopic), CP_WINNEUTRAL) != 0) { if (DdeQueryString(_dti.dwDDEInst, hszParams, szParams, ARRAYSIZE(szParams), CP_WINNEUTRAL)) { hddRet = CallTopic(XTYP_REQUEST, szTopic, szParams); } else { TraceMsg(TF_WARNING, "IEDDE: OnRequestPoke could not query the parameters"); } } else { TraceMsg(TF_WARNING, "IEDDE: OnRequestPoke could not query the topic"); }
EXITPROC(2, TEXT("OnRequestPoke=%08X"), hddRet); return hddRet; }
//
// OnExecute - handle XTYP_EXECUTE
//
HDDEDATA CIEDDEThread::OnExecute(HSZ hszTopic, HDDEDATA hddParams) { HDDEDATA hddRet = 0; ENTERPROC(2, TEXT("OnExecute(hszTopic=%08X,hddParams=%08X)"), hszTopic, hddParams);
TCHAR szTopic[100];
if (DdeQueryString(_dti.dwDDEInst, hszTopic, szTopic, ARRAYSIZE(szTopic), CP_WINNEUTRAL) != 0) { //
// Why "cbParams + 3"?
// UNICODE - if we cut the last unicode character in half, we need
// one 0 to finish the character, and two more 0 for the
// terminating NULL
// ANSI - if we cut the last DBCS character in half, we need one 0
// to finish the character, and one 0 for the terminating NULL
//
//
DWORD cbParams = DdeGetData(hddParams, NULL, 0, 0) + 3; LPTSTR pszParams = (LPTSTR) LocalAlloc(LPTR, cbParams);
if(pszParams) { DdeGetData(hddParams, (BYTE *)pszParams, cbParams, 0); //
// DdeGetData can't be wrapped in shlwapi since it can return non
// string data. Here we only expect strings so the result can be
// safely converted.
//
if (g_fRunningOnNT) { hddRet = CallTopic(XTYP_EXECUTE, szTopic, pszParams); } else { WCHAR szParams[MAX_URL_STRING]; SHAnsiToUnicode((LPCSTR)pszParams, szParams, ARRAYSIZE(szParams)); hddRet = CallTopic(XTYP_EXECUTE, szTopic, szParams); } LocalFree(pszParams); pszParams = NULL; } else { TraceMsg(TF_WARNING, "IEDDE: OnExecute could not query the topic"); } } else { TraceMsg(TF_WARNING, "IEDDE: OnExecute could not query the topic"); }
EXITPROC(2, TEXT("OnExecute=%08X"), hddRet); return hddRet; }
//
// CallTopic - Looks up the command in the DDETOPICHANDLER table and calls the
// corresponding function.
//
HDDEDATA CIEDDEThread::CallTopic(DWORD dwType, LPCTSTR pszTopic, LPTSTR pszParams) { HDDEDATA hddRet = DDE_FNOTPROCESSED; ENTERPROC(2, TEXT("CallTopic(wType=%d,pszTopic=>%s<,pszParams=>%s<)"), dwType, pszTopic, pszParams);
#define DISPATCH_BEGIN
#define DISPATCH(topic) \
if (StrCmpI(TEXT("WWW_") TEXT(#topic), pszTopic) == 0) \ { \ if (fCanRun) \ { \ hddRet = WWW_ ## topic(pszParams); \ } \ else \ { \ fAbortedRun = TRUE; \ } \ } \ else #define DISPATCH_END { TraceMsg(TF_WARNING, "IEDDE: CallTopic given unknown topic"); }
BOOL fAbortedRun = FALSE; BOOL fCanRun = ((dwType != XTYP_EXECUTE) || g_pIEDDE->IsAutomationReady());
DISPATCH_BEGIN DISPATCH(GetWindowInfo) DISPATCH(OpenURL) DISPATCH(ShowFile) DISPATCH(Activate) DISPATCH(Exit) DISPATCH(RegisterURLEcho) DISPATCH(UnregisterURLEcho) DISPATCH(RegisterProtocol) DISPATCH(UnregisterProtocol) DISPATCH(ListWindows) DISPATCH(OpenURLNewWindow) DISPATCH_END
if (fAbortedRun) { if (dwType == XTYP_EXECUTE) { g_pIEDDE->SetDelayedExecute(pszTopic, pszParams); } hddRet = (HDDEDATA)DDE_FACK; TraceMsg(TF_WARNING, "IEDDE: CallTopic received XTYP_EXECUTE before Automation was ready - not processing"); }
EXITPROC(2, TEXT("CallTopic=%08X"), hddRet); return hddRet; }
//
// ParseString - parse one string
//
BOOL CIEDDEThread::ParseString(LPTSTR *ppsz, LPTSTR *ppszString) { BOOL fRet = FALSE;
ENTERPROC(3, TEXT("ParseString(ppsz=%08X,ppszString=%08X)"), ppsz, ppszString);
LPTSTR pchCurrent, pchNext; BOOL fInQuote = FALSE;
pchCurrent = pchNext = *ppsz; while (*pchNext) { switch (*pchNext) { case TEXT(' '): case TEXT('\t'): if (fInQuote) { //
// Skip over whitespace when not inside quotes.
//
*pchCurrent++ = *pchNext; } pchNext++; break;
case TEXT('"'): //
// Always copy quote marks.
//
fInQuote = !fInQuote; *pchCurrent++ = *pchNext++; break;
case TEXT(','): if (!fInQuote) { goto done_parsing; } *pchCurrent++ = *pchNext++; break;
case TEXT('\\'): if (fInQuote && (*(pchNext+1) == TEXT('"'))) { //
// When in quotes, a \" becomes a ".
//
pchNext++; } *pchCurrent++ = *pchNext++; break;
default: *pchCurrent++ = *pchNext++; break; } } done_parsing:
//
// Advance past the comma separator.
//
if (*pchNext == TEXT(',')) { pchNext++; }
//
// NULL terminate the return string.
//
*pchCurrent = TEXT('\0');
//
// Set the return values.
//
*ppszString = *ppsz; *ppsz = pchNext; fRet = TRUE;
EXITPROC(3, TEXT("ParseString=%d"), fRet); return fRet; }
//
// ParseQString - parse one quoted string
//
BOOL CIEDDEThread::ParseQString(LPTSTR *ppsz, LPTSTR *ppszString) { BOOL fRet = FALSE;
ENTERPROC(3, TEXT("ParseQString(ppsz=%08X,ppszString=%08X)"), ppsz, ppszString);
if (ParseString(ppsz, ppszString)) { LPTSTR pszString = *ppszString; int cch = lstrlen(pszString);
//
// Strip off optional outer quotes.
//
if ((cch >= 2) && (pszString[0] == TEXT('"')) && (pszString[cch-1] == TEXT('"'))) { pszString[0] = pszString[cch-1] = TEXT('\0'); *ppszString = pszString + 1; }
fRet = TRUE; }
EXITPROC(3, TEXT("ParseQString=%d"), fRet); return fRet; }
//
// ParseNumber - parse one numeric value
//
BOOL CIEDDEThread::ParseNumber(LPTSTR *ppsz, DWORD *pdw) { BOOL fRet = FALSE; LPTSTR pszNumber;
ENTERPROC(3, TEXT("GetNumber(ppsz=%08X,pdw=%08X)"), ppsz, pdw);
if (ParseString(ppsz, &pszNumber) && pszNumber[0]) { StrToIntEx(pszNumber, STIF_SUPPORT_HEX, (int *)pdw); fRet = TRUE; }
EXITPROC(3, TEXT("GetNumber=%d"), fRet); return fRet; }
//
// ParseWinitem - parse one window ID, and return the winitem
//
BOOL CIEDDEThread::ParseWinitem(LPTSTR *ppsz, WINITEM *pwi) { BOOL fRet = FALSE; DWORD dwWindowID;
ENTERPROC(3, TEXT("ParseWinitem(ppsz=%08X,pwi=%08X)"), ppsz, pwi);
if (ParseNumber(ppsz, &dwWindowID)) { switch (dwWindowID) { case 0: case -1: ZeroMemory(pwi, SIZEOF(*pwi)); pwi->dwWindowID = dwWindowID; pwi->hwnd = (HWND)LongToHandle(dwWindowID); fRet = TRUE; break;
default: fRet = g_pIEDDE->GetWinitemFromWindowID(dwWindowID, pwi); break; } }
EXITPROC(3, TEXT("ParseWinitem=%d"), fRet); return fRet; }
//
// WWW_GetWindowInfo - get information about a browser window
//
// Parameters:
// dwWindowID - Window ID to examine (-1 = last active window)
//
// Returns:
// qcsURL,qcsTitle
//
HDDEDATA CIEDDEThread::WWW_GetWindowInfo(LPTSTR pszParams) { HDDEDATA hddRet = 0; WINITEM wi;
ENTERPROC(1, TEXT("WWW_GetWindowInfo(pszParams=>%s<)"), pszParams);
if (ParseWinitem(&pszParams, &wi) && (wi.hwnd != 0)) { BSTR bstrURL;
if (SUCCEEDED(CDDEAuto_get_LocationURL(&bstrURL, wi.hwnd)) && (bstrURL != (BSTR)-1)) { BSTR bstrTitle;
if (SUCCEEDED(CDDEAuto_get_LocationTitle(&bstrTitle, wi.hwnd)) && (bstrTitle != (BSTR)-1)) { LPTSTR pszURL, pszTitle;
pszURL = bstrURL; pszTitle = bstrTitle;
if (pszURL && pszTitle) { TCHAR szURLQ[MAX_URL_STRING]; TCHAR szTitleQ[MAX_URL_STRING];
if (MakeQuotedString(pszURL, szURLQ, ARRAYSIZE(szURLQ)) && MakeQuotedString(pszTitle, szTitleQ, ARRAYSIZE(szTitleQ))) { DWORD cchBuffer = lstrlen(szURLQ) + 1 + lstrlen(szTitleQ) + 1; LPTSTR pszBuffer = (LPTSTR)LocalAlloc(LPTR, cchBuffer * SIZEOF(TCHAR));
if (pszBuffer) { wnsprintf(pszBuffer, cchBuffer, TEXT("%s,%s"), szURLQ, szTitleQ); hddRet = CreateReturnStringObject(pszBuffer, lstrlen(pszBuffer)); LocalFree(pszBuffer); pszBuffer = NULL; } else { TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not alloc buffer"); } } else { TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not quote return strings"); } }
SysFreeString(bstrTitle); } else { TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not get title"); }
SysFreeString(bstrURL); } else { TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not get URL"); } } else { TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not parse parameters"); }
EXITPROC(1, TEXT("WWW_GetWindowInfo=%08X"), hddRet); return hddRet; }
//
// WWW_OpenURLNewWindow - navigate to a URL (but make sure to spawn a new window)
//
// NOTE: this code was stolen from IEDDEThread::WWW_OpenURL below
//
HDDEDATA CIEDDEThread::WWW_OpenURLNewWindow(LPTSTR pszParams) { HDDEDATA hddRet = 0; LPTSTR pszUrl, pszFile;
ENTERPROC(1, TEXT("WWW_OpenURLNewWindow(pszParams=>%s<)"), pszParams);
if (*pszParams == TEXT('\0') || *pszParams == TEXT('*')) { // An empty string is a NOOP.
} else if (ParseQString(&pszParams, &pszUrl) && ParseQString(&pszParams, &pszFile)) { // null hwnd & bLaunchNewWindow = TRUE means "launch a new window",
// which is exactly what we want to do in the WWW_OpenURLNewWindow case
hddRet = DoNavigate(pszUrl, NULL, TRUE); } else { TraceMsg(TF_WARNING, "IEDDE: WWW_OpenURLNewWindow could not parse parameters"); }
EXITPROC(1, TEXT("WWW_OpenURL=%08X"), hddRet); return hddRet; }
//
// WWW_OpenURL - navigate to a URL
//
// Parameters:
// qcsURL - url to navigate to
// qcsSaveFile - [optional] file to save contents in
// dwWindowID - Window ID to perform navigation
// dwFlags - flags for navigation
// qcsPostFormData - [optional] form data to post to URL
// qcsPostMIMEType - [optional] mime type for form data
// csProgressServer - [optional] DDE server to get progress updates
//
// Returns:
// dwWindowID - window which is doing the work
//
HDDEDATA CIEDDEThread::WWW_OpenURL(LPTSTR pszParams) { HDDEDATA hddRet = 0; LPTSTR pszUrl, pszFile; WINITEM wi;
ENTERPROC(1, TEXT("WWW_OpenURL(pszParams=>%s<)"), pszParams);
if (*pszParams == TEXT('\0') || *pszParams == TEXT('*')) { // An empty string is a NOOP. Needed for NT #291766
} else if (ParseQString(&pszParams, &pszUrl) && ParseQString(&pszParams, &pszFile)) { //
// APPCOMPAT - a missing hwnd parameter implies -1.
//
if (!ParseWinitem(&pszParams, &wi)) { TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required hwnd parameter to WWW_OpenURL, assuming -1"); wi.hwnd = (HWND)-1; }
#ifdef DEBUG
DWORD dwFlags; if (!ParseNumber(&pszParams, &dwFlags)) { TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required dwFlags parameter to WWW_OpenURL"); } #endif
hddRet = DoNavigate(pszUrl, wi.hwnd, FALSE); } else { TraceMsg(TF_WARNING, "IEDDE: OpenURL could not parse parameters"); }
EXITPROC(1, TEXT("WWW_OpenURL=%08X"), hddRet); return hddRet; }
//
// WWW_ShowFile - navigate to a file
//
// Parameters:
// qcsFilename - file to load
// qcsPostMIMEType - [optional] mime type for form data
// dwWindowID - Window ID to perform navigation
// qcsURL - URL of the same document
//
// Returns:
// dwWindowID - window which is doing the work
//
HDDEDATA CIEDDEThread::WWW_ShowFile(LPTSTR pszParams) { HDDEDATA hddRet = 0; LPTSTR pszFilename, pszMIMEType; WINITEM wi;
ENTERPROC(1, TEXT("WWW_ShowFile(pszParams=>%s<)"), pszParams);
if (ParseQString(&pszParams, &pszFilename) && pszFilename[0]) { if (!ParseQString(&pszParams, &pszMIMEType) || !pszMIMEType[0]) { TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required MIMEType parameter to WWW_ShowFile"); } if (!ParseWinitem(&pszParams, &wi)) { TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required dwWindowID parameter to WWW_ShowFile, assuming -1"); wi.hwnd = (HWND)-1; }
#ifdef DEBUG
LPTSTR pszURL;
if (!ParseQString(&pszParams, &pszURL) || !pszURL[0]) { TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required szURL parameter to WWW_ShowFile"); } #endif
hddRet = DoNavigate(pszFilename, wi.hwnd, FALSE); } else { TraceMsg(TF_WARNING, "IEDDE: ShowFile could not parse parameters"); }
EXITPROC(1, TEXT("WWW_ShowFile=%08X"), hddRet); return hddRet; }
//
// DoNavigate - navigate to a location
//
HDDEDATA CIEDDEThread::DoNavigate(LPTSTR pszLocation, HWND hwnd, BOOL bLaunchNewWindow) { HDDEDATA hddRet = 0; HRESULT hr = S_OK; TCHAR szParsedPath[MAX_URL_STRING+1]; DWORD cchParsedPath = ARRAYSIZE(szParsedPath);
ENTERPROC(2, TEXT("DoNavigate(pszLocation=>%s<,hwnd=%08X)"), pszLocation, hwnd);
//
// Convert URL from outside format to internal format.
//
if (ParseURLFromOutsideSource(pszLocation, szParsedPath, &cchParsedPath, NULL)) { pszLocation = szParsedPath; }
//
// In the case of a file:// URL, convert the location to a path.
//
cchParsedPath = ARRAYSIZE(szParsedPath); if (IsFileUrlW(pszLocation) && SUCCEEDED(PathCreateFromUrl(pszLocation, szParsedPath, &cchParsedPath, 0))) { pszLocation = szParsedPath; }
LPWSTR pwszPath;
pwszPath = pszLocation;
if (SUCCEEDED(hr)) { hr = CDDEAuto_Navigate(pwszPath, &hwnd, bLaunchNewWindow ? 1 : 0); }
DWORD dwServicingWindow = SUCCEEDED(hr) ? -2 : -3;
hddRet = CREATE_HDD(dwServicingWindow);
EXITPROC(2, TEXT("DoNavigate=%08X"), hddRet); return hddRet; }
//
// WWW_Activate - activate a browser window
//
// Parameters:
// dwWindowID - Window ID to activate
// dwFlags - should always zero
//
// Returns:
// dwWindowID - window ID that got activated
//
HDDEDATA CIEDDEThread::WWW_Activate(LPTSTR pszParams) { HDDEDATA hddRet = 0; WINITEM wi;
ENTERPROC(1, TEXT("WWW_Activate(pszParams=>%s<)"), pszParams);
if (ParseWinitem(&pszParams, &wi) && wi.dwWindowID != 0) { #ifdef DEBUG
DWORD dwFlags; if (ParseNumber(&pszParams, &dwFlags)) { //
// Netscape spec says this should always be zero.
//
ASSERT(dwFlags == 0); } else { TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required dwFlags parameter to WWW_Activate"); } #endif
//
// dwWindowID of -1 means use the active window.
//
if (wi.dwWindowID == -1) { HWND hwnd;
CDDEAuto_get_HWND((long *)&hwnd);
if (hwnd) { if (g_pIEDDE->GetWinitemFromHwnd(hwnd, &wi) == FALSE) { wi.dwWindowID = (DWORD)-1; } } else { TraceMsg(TF_WARNING, "IEDDE: Activate could not find an active window"); } }
//
// Activate the window.
//
if (wi.dwWindowID != -1) { if ((GetForegroundWindow() == wi.hwnd) || (SetForegroundWindow(wi.hwnd))) { if (IsIconic(wi.hwnd)) { ShowWindow(wi.hwnd, SW_RESTORE); } } else { TraceMsg(TF_WARNING, "IEDDE: Activate could not set foreground window"); } hddRet = CREATE_HDD(wi.dwWindowID); } else { TraceMsg(TF_WARNING, "IEDDE: Activate could not find a browser window to activate"); } } else { TraceMsg(TF_WARNING, "IEDDE: Activate could not parse parameters"); }
EXITPROC(1, TEXT("WWW_Activate=%08X"), hddRet); return hddRet; }
//
// WWW_Exit - close all browser windows
//
// Parameters:
// none
//
// Returns:
// none
//
HDDEDATA CIEDDEThread::WWW_Exit(LPTSTR pszParams) { HDDEDATA hddRet = 0;
ENTERPROC(1, TEXT("WWW_Exit(pszParams=>%s<)"), pszParams);
CDDEAuto_Exit();
EXITPROC(1, TEXT("WWW_Exit=%08X"), hddRet); return hddRet; }
//
// WWW_RegisterURLEcho - register a server for URL change notifications
//
// Parameters:
// qcsServer - the DDE server to get notifications
//
// Returns:
// fSuccess
//
HDDEDATA CIEDDEThread::WWW_RegisterURLEcho(LPTSTR pszParams) { HDDEDATA hddRet = 0; BOOL fSuccess = FALSE; LPTSTR pszServer;
ENTERPROC(1, TEXT("WWW_RegisterURLEcho(pszParams=>%s<)"), pszParams);
if (ParseQString(&pszParams, &pszServer) && pszServer[0]) { LPTSTR pszServerCopy = StrDup(pszServer);
if (pszServerCopy) { if (g_pIEDDE->AddUrlEcho(pszServerCopy)) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: RegisterURLEcho could not add an URLEcho"); }
if (!fSuccess) { LocalFree(pszServerCopy); pszServerCopy = NULL; } } else { TraceMsg(TF_WARNING, "IEDDE: RegisterURLEcho could not dup a string"); } } else { TraceMsg(TF_WARNING, "IEDDE: RegisterURLEcho could not parse parameters"); }
hddRet = CREATE_HDD(fSuccess);
EXITPROC(1, TEXT("WWW_RegisterURLEcho=%08X"), hddRet); return hddRet; }
//
// WWW_UnregisterURLEcho - unregister a DDE server
//
// Parameters:
// qcsServer - the DDE server to stop getting notifications
//
// Returns:
// fSuccess
//
HDDEDATA CIEDDEThread::WWW_UnregisterURLEcho(LPTSTR pszParams) { HDDEDATA hddRet = 0; BOOL fSuccess = FALSE; LPTSTR pszServer;
ENTERPROC(1, TEXT("WWW_UnregisterURLEcho(pszParams=>%s<)"), pszParams);
if (ParseQString(&pszParams, &pszServer) && pszServer[0]) { if (g_pIEDDE->RemoveUrlEcho(pszServer)) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: UnregisterURLEcho could not find the server"); } } else { TraceMsg(TF_WARNING, "IEDDE: UnregisterURLEcho could not parse parameters"); }
hddRet = CREATE_HDD(fSuccess);
EXITPROC(1, TEXT("WWW_UnregisterURLEcho=%08X"), hddRet); return hddRet; }
//
// WWW_RegisterProtocol - register a server for handling a protocol
//
// Parameters:
// qcsServer - the DDE server to handle URLs
// qcsProtocol - the protocol to handle
//
// Returns:
// fSuccess - this is the first server to register the protocol
//
HDDEDATA CIEDDEThread::WWW_RegisterProtocol(LPTSTR pszParams) { HDDEDATA hddRet = 0; BOOL fSuccess = FALSE; LPTSTR pszServer, pszProtocol;
ENTERPROC(1, TEXT("WWW_RegisterProtocol(pszParams=>%s<)"), pszParams);
if (ParseQString(&pszParams, &pszServer) && pszServer[0] && ParseQString(&pszParams, &pszProtocol) && pszProtocol[0]) { if (g_pIEDDE->AddProtocolHandler(pszServer, pszProtocol)) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: RegisterProtocol unable to register"); } } else { TraceMsg(TF_WARNING, "IEDDE: RegisterProtocol could not parse parameters"); }
hddRet = CREATE_HDD(fSuccess);
EXITPROC(1, TEXT("WWW_RegisterProtocol=%08X"), hddRet); return hddRet; }
//
// WWW_UnregisterProtocol - unregister a server handling a protocol
//
// Parameters:
// qcsServer - the DDE server which is handling URLs
// qcsProtocol - the protocol getting handled
//
// Returns:
// fSuccess - this server was registered, but now isn't
//
HDDEDATA CIEDDEThread::WWW_UnregisterProtocol(LPTSTR pszParams) { HDDEDATA hddRet = 0; BOOL fSuccess = FALSE; LPTSTR pszServer, pszProtocol;
ENTERPROC(1, TEXT("WWW_UnregisterProtocol(pszParams=>%s<)"), pszParams);
if (ParseQString(&pszParams, &pszServer) && pszServer[0] && ParseQString(&pszParams, &pszProtocol) && pszProtocol[0]) { if (g_pIEDDE->RemoveProtocolHandler(pszServer, pszProtocol)) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: UnregisterProtocol unable to unregister"); } } else { TraceMsg(TF_WARNING, "IEDDE: UnregisterProtocol could not parse parameters"); }
hddRet = CREATE_HDD(fSuccess);
EXITPROC(1, TEXT("WWW_UnregisterProtocol=%08X"), hddRet); return hddRet; }
//
// WWW_ListWindows - Get a list of DDE supported browser window IDs
//
// Parameters:
// none
//
// Returns:
// pdwWindowID (terminated with 0)
//
HDDEDATA CIEDDEThread::WWW_ListWindows(LPTSTR pszParams) { HDDEDATA hddRet = 0; ENTERPROC(1, TEXT("WWW_ListWindows(pszParams=>%s<)"), pszParams);
ENTER_IEDDE_CRIT;
DWORD cbAlloc, *pdwWindowID; int cWindows = 0; HDSA hdsaWinitem = g_pIEDDE->GetHdsaWinitem();
if (hdsaWinitem) { cWindows = DSA_GetItemCount(hdsaWinitem); }
//
// Note: we are following the Netscape spec (null terminated pdw) here,
// whereas IE3 followed the Spyglass spec (pdw[0] = count of windows).
//
cbAlloc = (cWindows + 1) * SIZEOF(DWORD);
pdwWindowID = (DWORD *)LocalAlloc(LPTR, cbAlloc); if (pdwWindowID) { DWORD *pdw;
pdw = pdwWindowID;
for (int i=0; i<cWindows; i++) { WINITEM wi;
int iResult = DSA_GetItem(hdsaWinitem, i, &wi);
if (iResult != -1) { *pdw++ = wi.dwWindowID; } else { TraceMsg(TF_WARNING, "IEDDE: ListWindows could not get a DSA item"); } }
hddRet = CreateReturnObject(pdwWindowID, cbAlloc); } else { TraceMsg(TF_WARNING, "IEDDE: ListWindows could not allocate a window list"); }
LEAVE_IEDDE_CRIT;
EXITPROC(1, TEXT("WWW_ListWindows=%08X"), hddRet); return hddRet; }
//
// MakeQuotedString - wrap a string in " marks, escaping internal "s as \"
//
BOOL CIEDDEThread::MakeQuotedString(LPCTSTR pszInput, LPTSTR pszOutput, int cchOutput) { BOOL fRet = FALSE;
ENTERPROC(2, TEXT("MakeQuotedString(pszInput=>%s<,pszOutput=%08X,cchOutput=%08X)"), pszInput, pszOutput, cchOutput);
if (cchOutput < 3) { TraceMsg(TF_WARNING, "IEDDE: MakeQuotedString has no room for minimal quoted string"); } else if ((pszInput == NULL) || (*pszInput == TEXT('\0'))) { StrCpyN(pszOutput, TEXT("\"\""), cchOutput); fRet = TRUE; } else { //
// Copy first quote mark.
//
*pszOutput++ = TEXT('"'); cchOutput--;
//
// Copy pszInput, escaping quote marks and making
// sure to leave room for final quote and NULL.
//
while ((cchOutput > 2) && (*pszInput)) { if (*pszInput == TEXT('"')) { *pszOutput++ = TEXT('\\'); cchOutput--; } *pszOutput++ = *pszInput++; cchOutput--; }
//
// Copy final quote and NULL if we're done and there is room.
//
if ((*pszInput == TEXT('\0')) && (cchOutput >= 2)) { StrCpyN(pszOutput, TEXT("\""), cchOutput); fRet = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: MakeQuotedString ran out of room in output buffer"); } }
EXITPROC(2, TEXT("MakeQuotedString=%d"), fRet); return fRet; }
#undef CIEDDEThread
//
// There is one global CIEDDE object per process.
// It maintains the global information, such as
// the list of all browsers & what threads they are on,
// and the list of all apps who have registered an URL Echo.
//
// Its methods consist of these categories:
// the DDE callback function
// an internal handler for each exposed IEDDE_ function
// database (hdsa, hdpa) access and manipulation functions
//
// This object creates and destroys CIEDDEThread objects
// (at NewWindow and WindowDestroyed time) and also initializes /
// uninitializes DDE services on a per thread (not per hwnd!) basis.
//
//
// DdeCallback - DDE callback function for IEDDE.
//
#define DDETYPESTR(x) (x == XTYP_REQUEST ? TEXT("Request") : \
(x == XTYP_POKE ? TEXT("Poke") : \ (x == XTYP_EXECUTE ? TEXT("Execute") : \ (x == XTYP_CONNECT ? TEXT("Connect") : TEXT("Unknown"))))) HDDEDATA CIEDDE::DdeCallback(UINT dwType, UINT dwFmt, HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hdd, DWORD dwData1, DWORD dwData2) { HDDEDATA hddRet = 0; ENTERPROC(2, TEXT("DdeCallback(dwType=%08X(%s),dwFmt=%d,hconv=%d,hsz1=%08X,hsz2=%08X,hdd=%08X,dwData1=%08X,dwData2=%08X)"), dwType, DDETYPESTR(dwType), dwFmt, hconv, hsz1, hsz2, hdd, dwData1, dwData2);
WINITEM wi;
switch (dwType) { case XTYP_REQUEST: case XTYP_POKE: if (g_pIEDDE->_GetWinitemFromThread(GetCurrentThreadId(), &wi)) { hddRet = wi.pidt->OnRequestPoke(hsz1, hsz2); } else { TraceMsg(TF_WARNING, "IEDDE: DdeCallback unable to get thread info on request / poke"); } break;
case XTYP_EXECUTE: if (g_pIEDDE->_GetWinitemFromThread(GetCurrentThreadId(), &wi)) { hddRet = wi.pidt->OnExecute(hsz1, hdd); } else { TraceMsg(TF_WARNING, "IEDDE: DdeCallback unable to get thread info on execute"); } break;
case XTYP_CONNECT: if (g_pIEDDE->_GetWinitemFromThread(GetCurrentThreadId(), &wi)) { DDETHREADINFO dti; wi.pidt->GetDdeThreadInfo(&dti); hddRet = (HDDEDATA)(hsz2 == dti.hszService); } else { TraceMsg(TF_WARNING, "IEDDE: DdeCallback unable to get thread info on connect"); } break;
case XTYP_ADVREQ: case XTYP_ADVSTOP: hddRet = DDE_FNOTPROCESSED; break; }
EXITPROC(2, TEXT("DdeCallback=%08X"), hddRet); return hddRet; }
//
// SendDDEMessageHsz - handle based wrapper for doing one DDE client transaction
//
HDDEDATA CIEDDE::_SendDDEMessageHsz(DWORD dwDDEInst, HSZ hszApp, HSZ hszTopic, HSZ hszMessage, UINT wType) { HDDEDATA hddRet = 0;
ENTERPROC(2, TEXT("_SendDDEMessageHsz(dwDDEInst=%08X,hszApp=%08X,hszTopic=%08X,hszMessage=%08X,wType=%d)"), dwDDEInst, hszApp, hszTopic, hszMessage, wType);
if (hszApp && hszTopic) { HCONV hconv; hconv = DdeConnect(dwDDEInst, hszApp, hszTopic, NULL); if (hconv) { hddRet = DdeClientTransaction(NULL, 0, hconv, hszMessage, CF_TEXT, wType, TEN_SECONDS, NULL); DdeDisconnect(hconv); } else { TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageHsz could not connect to app"); } } else { TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageHsz is missing either App or Topic"); }
EXITPROC(2, TEXT("_SendDDEMessageHsz=%08X"), hddRet); return hddRet; }
//
// SendDDEMessageSz - string based wrapper for doing one DDE client transaction
//
HDDEDATA CIEDDE::_SendDDEMessageSz(DWORD dwDDEInst, LPCTSTR pszApp, LPCTSTR pszTopic, LPCTSTR pszMessage, UINT wType) { HDDEDATA hddRet = 0;
ENTERPROC(2, TEXT("_SendDDEMessageSz(dwDDEInst=%08X,pszApp=>%s<,pszTopic=>%s<,pszMessage=>%s<,wType=%d)"), dwDDEInst, pszApp, pszTopic, pszMessage, wType);
HSZ hszApp = DdeCreateStringHandle(dwDDEInst, pszApp, CP_WINNEUTRAL); if (hszApp) { HSZ hszTopic = DdeCreateStringHandle(dwDDEInst, pszTopic, CP_WINNEUTRAL); if (hszTopic) { HSZ hszMessage = DdeCreateStringHandle(dwDDEInst, pszMessage, CP_WINNEUTRAL); if (hszMessage) { hddRet = _SendDDEMessageHsz(dwDDEInst, hszApp, hszTopic, hszMessage, wType); DdeFreeStringHandle(dwDDEInst, hszMessage); } else { TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageSz could not convert message"); } DdeFreeStringHandle(dwDDEInst, hszTopic); } else { TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageSz could not convert topic"); } DdeFreeStringHandle(dwDDEInst, hszApp); } else { TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageSz could not convert app"); }
EXITPROC(2, TEXT("_SendDDEMessageSz=%08X"), hddRet); return hddRet; }
//
// Initialize - called when ready to start IEDDE server
//
BOOL CIEDDE::_Initialize(void) { BOOL fSuccess = TRUE; ENTERPROC(2, TEXT("_Initialize()"));
ASSERT(_fCSInitialized == FALSE); InitializeCriticalSection(&_csIEDDE); _fCSInitialized = TRUE;
EXITPROC(2, TEXT("_Initialize=%d"), fSuccess); return fSuccess; }
//
// _DestroyWinitem - DSA callback to partially free the contents of a WINITEM*
// In practice this should never get called, the hdsaWinItem list should be
// empty at uninit time.
//
int CIEDDE::_DestroyWinitem(LPVOID p1, LPVOID p2) { WINITEM *pwi = (WINITEM *)p1; ASSERT(IS_VALID_READ_PTR(pwi, WINITEM)); ASSERT(IS_VALID_READ_PTR(pwi->pidt, CIEDDEThread));
//
// It would be good to unregister the DDE server at this point,
// but we'd need to be on its thread to do it.
//
delete pwi->pidt;
return 1; }
//
// _DestroyProtocol - DSA callback to free the contents of a PROTOCOLREG*
//
int CIEDDE::_DestroyProtocol(LPVOID p1, LPVOID p2) { PROTOCOLREG *pr = (PROTOCOLREG *)p1; ASSERT(IS_VALID_READ_PTR(pr, PROTOCOLREG));
LocalFree(pr->pszProtocol); pr->pszProtocol = NULL; LocalFree(pr->pszServer); pr->pszServer = NULL;
return 1; }
//
// _DestroyUrlEcho - DPA callback to free allocated memory
//
int CIEDDE::_DestroyUrlEcho(LPVOID p1, LPVOID p2) { ASSERT(IS_VALID_STRING_PTR((LPTSTR)p1, -1)); LocalFree(p1); p1 = NULL;
return 1; }
//
// Uninitialize - called when ready to stop IEDDE server
//
void CIEDDE::_Uninitialize(void) { ENTERPROC(2, TEXT("_Uninitialize()"));
_fAutomationReady = FALSE;
if (_hdsaWinitem) { if (DSA_GetItemCount(_hdsaWinitem)) { //ASSERT(DSA_GetItemCount(_hdsaWinitem)==0);
TraceMsg(TF_ERROR, "IEDDE: Browser windows still open on uninitialize"); }
DSA_DestroyCallback(_hdsaWinitem, _DestroyWinitem, 0); _hdsaWinitem = NULL; }
if (_hdsaProtocolHandler) { DSA_DestroyCallback(_hdsaProtocolHandler, _DestroyProtocol, 0); _hdsaProtocolHandler = NULL; }
if (_hdpaUrlEcho) { DPA_DestroyCallback(_hdpaUrlEcho, _DestroyUrlEcho, 0); _hdpaUrlEcho = NULL; }
if (_fCSInitialized) { DeleteCriticalSection(&_csIEDDE); }
EXITPROC(2, TEXT("_Uninitialize!")); }
void CIEDDE::SetDelayedExecute(LPCTSTR pszTopic, LPCTSTR pszParams) { _dwThreadID = GetCurrentThreadId(); Str_SetPtr(&_pszTopic, pszTopic); Str_SetPtr(&_pszParams, pszParams); }
void CIEDDE::RunDelayedExecute() { if (_pszTopic && _pszParams) { WINITEM wi; if (_GetWinitemFromThread(_dwThreadID, &wi) && wi.pidt) { HDDEDATA h = wi.pidt->CallTopic(XTYP_EXECUTE, _pszTopic, _pszParams); DdeFreeDataHandle(h); } }
Str_SetPtr(&_pszTopic, NULL); Str_SetPtr(&_pszParams, NULL); } //
// _AutomationStarted - called when automation support can be called
//
void CIEDDE::_AutomationStarted(void) { ENTERPROC(1, TEXT("_AutomationStarted()")); if (!_fAutomationReady && _pszTopic && _pszParams) { WINITEM wi; if (_GetWinitemFromThread(_dwThreadID, &wi) && wi.pidt) { PostMessage(wi.hwnd, WMC_DELAYEDDDEEXEC, 0, 0); } } _fAutomationReady = TRUE;
EXITPROC(1, TEXT("_AutomationStarted!")); }
//
// _BeforeNavigate - called before a navigation occurs.
//
HRESULT CIEDDE::_BeforeNavigate(LPCTSTR pszURL, BOOL *pfProcessed) { ENTERPROC(1, TEXT("_BeforeNavigate(pszURL=>%s<,pfProcessed=%08X)"), pszURL, pfProcessed);
SHSTR shstrMsg; HRESULT hr = S_OK; int cProtocols = 0;
ENTER_IEDDE_CRIT; if (_hdsaProtocolHandler) { cProtocols = DSA_GetItemCount(_hdsaProtocolHandler); } LEAVE_IEDDE_CRIT;
if (cProtocols) { DDETHREADINFO dti;
if (_GetDtiFromThread(GetCurrentThreadId(), &dti)) { PARSEDURL pu;
pu.cbSize = SIZEOF(pu);
if (SUCCEEDED(ParseURL(pszURL, &pu))) { int i;
for (i=0; i<cProtocols; i++) { PROTOCOLREG pr;
ENTER_IEDDE_CRIT; int iResult = DSA_GetItem(_hdsaProtocolHandler, i, &pr); LEAVE_IEDDE_CRIT;
if (iResult != -1) { //
// Check to see if the protocol to navigate
// matches one of our registered protocols.
// We do a case insensitive compare. Note
// that:
//
// (1) ParseURL does not null terminate the
// pu.pszProtocol (its length is stored
// in pu.cchProtocol).
//
// (2) pu.pszProtocol is a LPCTSTR so we
// can't modify the pszProtocol ourselves.
//
// (3) There is no win32 lstrncmpi() API.
//
// Therefore in order to do a case insensitive
// compare we must copy the pu.pszProtocol into
// a writable buffer at some point.
//
if (lstrlen(pr.pszProtocol) == (int)pu.cchProtocol) { shstrMsg.SetStr(pu.pszProtocol, pu.cchProtocol); if (StrCmpI(pr.pszProtocol, shstrMsg) == 0) { shstrMsg.SetStr(TEXT("\"")); shstrMsg.Append(pszURL); shstrMsg.Append(TEXT("\",,-1,0,,,,"));
if (_SendDDEMessageSz(dti.dwDDEInst, pr.pszServer, c_szWWWOpenURL, shstrMsg, XTYP_REQUEST)) { if (pfProcessed) { *pfProcessed = TRUE; } } else { TraceMsg(TF_WARNING, "IEDDE: _BeforeNavigate could not DDE to protocol handler"); }
break; } } } else { TraceMsg(TF_WARNING, "IEDDE: _BeforeNavigate could not get item from DSA"); } } } else { TraceMsg(TF_WARNING, "IEDDE: _BeforeNavigate could not parse URL"); } } else { TraceMsg(TF_WARNING, "IEDDE: _BeforeNavigate unable to get thread info, can't use DDE"); } }
EXITPROC(1, TEXT("_BeforeNavigate=%08X"), hr); return hr; }
//
// _AfterNavigate - called after a navigation occurs
//
HRESULT CIEDDE::_AfterNavigate(LPCTSTR pszURL, HWND hwnd) { ENTERPROC(1, TEXT("_AfterNavigate(pszURL=>%s<,hwnd=%08X)"), pszURL, hwnd);
int cURLHooks = 0; SHSTR shstrMsg; HRESULT hr = S_OK;
ENTER_IEDDE_CRIT; if (_hdpaUrlEcho) { cURLHooks = DPA_GetPtrCount(_hdpaUrlEcho); } LEAVE_IEDDE_CRIT;
if (cURLHooks) { SHSTR shstrMime;
// (mattsq 1-97)
// this is a temporary lie - it should be fixed to use the real mimetype
// with something like:
// GetMimeTypeFromUrl(pszURL, shstrMime);
// talk to URLMON people
shstrMime.SetStr(TEXT("text/html"));
DDETHREADINFO dti={0}; WINITEM wi; DWORD dwWindowID; if (GetWinitemFromHwnd(hwnd, &wi)) { dwWindowID = wi.dwWindowID; wi.pidt->GetDdeThreadInfo(&dti); } else { TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to find browser window ID, using -1"); dwWindowID = (DWORD)-1;
WINITEM wiThread;
if (_GetWinitemFromThread(GetCurrentThreadId(), &wiThread)) { ASSERT(wiThread.pidt); wiThread.pidt->GetDdeThreadInfo(&dti); } else { TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to find DDE thread info"); } }
if (dti.dwDDEInst) { HSZ hszTopic = DdeCreateStringHandle(dti.dwDDEInst, c_szWWWUrlEcho, CP_WINNEUTRAL); if (hszTopic) { TCHAR szFinish[16];
shstrMsg.SetStr(TEXT("\"")); // Quote
shstrMsg.Append(pszURL); // URL
shstrMsg.Append(TEXT("\",\"")); // Quote Comma Quote
shstrMsg.Append(shstrMime); // Mime
wnsprintf(szFinish, ARRAYSIZE(szFinish), TEXT("\",%d"), dwWindowID); //
shstrMsg.Append(szFinish); // Quote Comma dwWindowID NULL
HSZ hszMsg = DdeCreateStringHandle(dti.dwDDEInst, shstrMsg, CP_WINNEUTRAL);
if (hszMsg) { //
// Enumerate in reverse order because calling a hook may destroy it.
//
for (int i=cURLHooks-1; i>=0; --i) { ENTER_IEDDE_CRIT; LPTSTR pszService = (LPTSTR)DPA_GetPtr(_hdpaUrlEcho, i); LEAVE_IEDDE_CRIT;
if (pszService != NULL) { HSZ hszService = DdeCreateStringHandle(dti.dwDDEInst, pszService, CP_WINNEUTRAL);
if (hszService) { if (_SendDDEMessageHsz(dti.dwDDEInst, hszService, hszTopic, hszMsg, XTYP_POKE) == 0) { TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate could not DDE to URLHook handler"); }
DdeFreeStringHandle(dti.dwDDEInst, hszService); } else { TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to create hszService"); } } else { TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to enumerate an URL hook"); } }
DdeFreeStringHandle(dti.dwDDEInst, hszMsg); } else { TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to create hszMsg"); }
DdeFreeStringHandle(dti.dwDDEInst, hszTopic); } else { TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to create hszTopic"); } } }
EXITPROC(1, TEXT("_AfterNavigate=%08X"), hr); return hr; }
//
// GetWinitemFromHwnd - return the winitem associated with an hwnd
//
BOOL CIEDDE::GetWinitemFromHwnd(HWND hwnd, WINITEM *pwi) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("GetWinitemFromHwnd(hwnd=%08X,pwi=%08X)"), hwnd, pwi);
ENTER_IEDDE_CRIT;
if (_hdsaWinitem) { for (int i=0; i<DSA_GetItemCount(_hdsaWinitem); i++) { WINITEM wi;
if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1) { if (wi.hwnd == hwnd) { *pwi = wi; fSuccess = TRUE; break; } } } }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("GetWinitemFromHwnd=%d"), fSuccess); return fSuccess; }
//
// GetWinitemFromWindowID - return the winitem associated with a window ID
//
BOOL CIEDDE::GetWinitemFromWindowID(DWORD dwWindowID, WINITEM *pwi) { BOOL fSuccess = FALSE; ENTERPROC(3, TEXT("GetWinitemFromWindowID(dwWindowID=%08X,pwi=%08X)"), dwWindowID, pwi);
ENTER_IEDDE_CRIT;
if (_hdsaWinitem) { for (int i=0; i<DSA_GetItemCount(_hdsaWinitem); i++) { WINITEM wi;
if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1) { if (wi.dwWindowID == dwWindowID) { *pwi = wi; fSuccess = TRUE; break; } } } }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("GetWinitemFromWindowID=%d"), fSuccess); return fSuccess; }
//
// _GetWinitemFromThread - return the first winitem associated with a thread
//
BOOL CIEDDE::_GetWinitemFromThread(DWORD dwThreadID, WINITEM *pwi) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("_GetWinitemFromThread(dwThreadID=%08X,pwi=%08X)"), dwThreadID, pwi);
ENTER_IEDDE_CRIT;
if (_hdsaWinitem) { for (int i=0; i<DSA_GetItemCount(_hdsaWinitem); i++) { WINITEM wi;
if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1) { if (wi.dwThreadID == dwThreadID) { *pwi = wi; fSuccess = TRUE; break; } } } }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("_GetWinitemFromThread=%d"), fSuccess); return fSuccess; }
//
// _GetDtiFromThread - return the threadinfo associated with a thread
//
BOOL CIEDDE::_GetDtiFromThread(DWORD dwThreadID, DDETHREADINFO *pdti) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("_GetDtiFromThread(dwThreadID=%08X,pdti=%08X)"), dwThreadID, pdti);
ENTER_IEDDE_CRIT;
WINITEM wi; if (_GetWinitemFromThread(dwThreadID, &wi)) { wi.pidt->GetDdeThreadInfo(pdti); fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: _GetDtiFromThread unable to find winitem"); }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("_GetDtiFromThread=%d"), fSuccess); return fSuccess; }
//
// _CreateDdeThreadInfo - Initialize DDE services and names for this thread
//
BOOL CIEDDE::_CreateDdeThreadInfo(DDETHREADINFO *pdti) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("_CreateDdeThreadInfo(pdti=%08X)"), pdti);
UINT uiDDE; DDETHREADINFO dti={0};
//
// Initialize DDEML, register our service.
//
uiDDE = DdeInitialize(&dti.dwDDEInst, (PFNCALLBACK)DdeCallback, APPCLASS_STANDARD | CBF_FAIL_ADVISES | CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS, 0);
if (uiDDE == DMLERR_NO_ERROR) { dti.hszReturn = DdeCreateStringHandle(dti.dwDDEInst, c_szReturn, CP_WINNEUTRAL); if (dti.hszReturn) { dti.hszService = DdeCreateStringHandle(dti.dwDDEInst, c_szIExplore, CP_WINNEUTRAL); if (dti.hszService) { *pdti = dti; fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: _CreateDdeThreadInfo unable to convert service"); }
if (!fSuccess) { DdeFreeStringHandle(dti.dwDDEInst, dti.hszReturn); } } else { TraceMsg(TF_WARNING, "IEDDE: _CreateDdeThreadInfo unable to convert return"); }
if (!fSuccess) { DdeUninitialize(dti.dwDDEInst); } } else { TraceMsg(TF_WARNING, "IEDDE: _CreateDdeThreadInfo unable to init DDE"); }
EXITPROC(2, TEXT("_CreateDdeThreadInfo=%d"), fSuccess); return fSuccess; }
//
// _DestroyDdeThreadInfo - Free up any resources in a dti structure.
//
void CIEDDE::_DestroyDdeThreadInfo(DDETHREADINFO *pdti) { ENTERPROC(2, TEXT("_DestroyDdeThreadInfo(pdti=%08X)"), pdti);
if (pdti->hddNameService) { ASSERT(pdti->hszService); DdeNameService(pdti->dwDDEInst, pdti->hszService, 0, DNS_UNREGISTER); pdti->hddNameService = 0; }
if (pdti->hszService) { DdeFreeStringHandle(pdti->dwDDEInst, pdti->hszService); pdti->hszService = 0; }
if (pdti->hszReturn) { DdeFreeStringHandle(pdti->dwDDEInst, pdti->hszReturn); pdti->hszReturn = 0; }
if (pdti->dwDDEInst) { DdeUninitialize(pdti->dwDDEInst); pdti->dwDDEInst = 0; }
EXITPROC(2, TEXT("_DestroyDdeThreadInfo!")); return; }
//
// _AddWinitem - adds a winitem to _hdsaWinitem
//
BOOL CIEDDE::_AddWinitem(WINITEM *pwi) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("_AddWinitem(pwi=%08X)"), pwi);
ENTER_IEDDE_CRIT;
if (!_hdsaWinitem) { _hdsaWinitem = DSA_Create(SIZEOF(WINITEM), DXA_GROWTH_AMOUNT); }
if (_hdsaWinitem) { if (DSA_AppendItem(_hdsaWinitem, pwi) != -1) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: _AddWinitem could not append an item"); } } else { TraceMsg(TF_WARNING, "IEDDE: _AddWinitem could not create hdsa"); }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("_AddWinitem=%d"), fSuccess); return fSuccess; }
//
// _UpdateWinitem - updates a winitem based on the dwWindowID.
//
BOOL CIEDDE::_UpdateWinitem(WINITEM *pwi) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("_UpdateWinitem(pwi=%08X)"), pwi);
ENTER_IEDDE_CRIT;
if (_hdsaWinitem) { int cItems = DSA_GetItemCount(_hdsaWinitem);
for (int i=0; i<cItems; i++) { WINITEM wi;
if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1) { if (wi.dwWindowID == pwi->dwWindowID) { if (DSA_SetItem(_hdsaWinitem, i, pwi)) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: _UpdateWinitem could not update an item"); } break; } } else { TraceMsg(TF_WARNING, "IEDDE: _UpdateWinitem could not get an item"); } } }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("_UpdateWinitem=%d"), fSuccess); return fSuccess; }
//
// AddUrlEcho - adds an UrlEcho entry to the dpa
//
BOOL CIEDDE::AddUrlEcho(LPCTSTR pszUrlEcho) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("AddUrlEcho(pszUrlEcho=>%s<)"), pszUrlEcho);
ENTER_IEDDE_CRIT;
if (!_hdpaUrlEcho) { _hdpaUrlEcho = DPA_Create(DXA_GROWTH_AMOUNT); }
if (_hdpaUrlEcho) { if (DPA_AppendPtr(_hdpaUrlEcho, (LPVOID)pszUrlEcho) != -1) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: AddUrlEcho unable to append a ptr"); } } else { TraceMsg(TF_WARNING, "IEDDE: AddUrlEcho unable to create a dpa"); }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("AddUrlEcho=%d"), fSuccess); return fSuccess; }
//
// RemoveUrlEcho - remove an UrlEcho entry from the dpa
//
BOOL CIEDDE::RemoveUrlEcho(LPCTSTR pszUrlEcho) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("RemoveUrlEcho(pszUrlEcho=>%s<)"), pszUrlEcho);
ENTER_IEDDE_CRIT;
if (_hdpaUrlEcho) { for (int i=0; i<DPA_GetPtrCount(_hdpaUrlEcho); i++) { LPTSTR pszList = (LPTSTR)DPA_GetPtr(_hdpaUrlEcho, i); if (pszList) { if (StrCmpI(pszList, pszUrlEcho) == 0) { DPA_DeletePtr(_hdpaUrlEcho, i); LocalFree((HANDLE)pszList); pszList = NULL; fSuccess = TRUE; break; } } else { TraceMsg(TF_ALWAYS, "IEDDE: RemoveUrlEcho unable to get dpa ptr"); } }
if (!fSuccess) { TraceMsg(TF_WARNING, "IEDDE: RemoveUrlEcho unable to find server"); } } else { TraceMsg(TF_WARNING, "IEDDE: RemoveUrlEcho unable to find dpa"); }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("RemoveUrlEcho=%d"), fSuccess); return fSuccess; }
//
// AddProtocolHandler - add a PROTOCOLREG entry to the dsa
//
BOOL CIEDDE::AddProtocolHandler(LPCTSTR pszServer, LPCTSTR pszProtocol) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("AddProtocolHandler(pszServer=>%s<,pszProtocol=>%s<)"), pszServer, pszProtocol);
ENTER_IEDDE_CRIT;
PROTOCOLREG pr; //
// First, see if anybody else grabbed the protocol first.
//
BOOL fFoundHandler = FALSE; if (_hdsaProtocolHandler) { for (int i=0; i<DSA_GetItemCount(_hdsaProtocolHandler); i++) { if (DSA_GetItem(_hdsaProtocolHandler, i, &pr) != -1) { if (StrCmpI(pr.pszProtocol, pszProtocol) == 0) { TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler already has a handler"); fFoundHandler = TRUE; break; } } else { TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to get an item"); } } }
if (!fFoundHandler) { if (!_hdsaProtocolHandler) { _hdsaProtocolHandler = DSA_Create(SIZEOF(PROTOCOLREG), DXA_GROWTH_AMOUNT); }
if (_hdsaProtocolHandler) { pr.pszServer = StrDup(pszServer); if (pr.pszServer) { pr.pszProtocol = StrDup(pszProtocol); if (pr.pszProtocol) { if (DSA_AppendItem(_hdsaProtocolHandler, &pr) != -1) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to append to dsa"); }
if (!fSuccess) { LocalFree((HANDLE)pr.pszProtocol); pr.pszProtocol = NULL; } } else { TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to dup protocol"); }
if (!fSuccess) { LocalFree((HANDLE)pr.pszServer); pr.pszServer = NULL; } } else { TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to dup server"); }
} else { TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to create dsa"); } }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("AddProtocolHandler=%d"), fSuccess); return fSuccess; }
//
// RemoveProtocolHandler - removes a PROTOCOLREG item from the dsa
//
BOOL CIEDDE::RemoveProtocolHandler(LPCTSTR pszServer, LPCTSTR pszProtocol) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("RemoveProtocolHandler(pszServer=>%s<,pszProtocol=>%s<)"), pszServer, pszProtocol);
ENTER_IEDDE_CRIT;
if (_hdsaProtocolHandler) { for (int i=0; i<DSA_GetItemCount(_hdsaProtocolHandler); i++) { PROTOCOLREG pr;
if (DSA_GetItem(_hdsaProtocolHandler, i, &pr) != -1) { if (StrCmpI(pr.pszProtocol, pszProtocol) == 0) { if (StrCmpI(pr.pszServer, pszServer) == 0) { if (DSA_DeleteItem(_hdsaProtocolHandler, i) != -1) { LocalFree((HANDLE)pr.pszServer); pr.pszServer = NULL; LocalFree((HANDLE)pr.pszProtocol); pr.pszProtocol = NULL; fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler unable to remove item"); } } else { TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler says server didn't match"); }
break; } } else { TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler unable to get item"); } }
if (!fSuccess) { TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler unable to complete mission"); } } else { TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler can't find the dsa"); }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("RemoveProtocolHandler=%d"), fSuccess); return fSuccess; }
//
// _DeleteWinitemByHwnd - removes a winitem from _hdsaWinitem
//
BOOL CIEDDE::_DeleteWinitemByHwnd(HWND hwnd, WINITEM *pwi) { BOOL fSuccess = FALSE; ENTERPROC(2, TEXT("_DeleteWinitemByHwnd(hwnd=%08X,pwi=%08X)"), hwnd, pwi);
ENTER_IEDDE_CRIT;
if (_hdsaWinitem) { for (int i=0; i<DSA_GetItemCount(_hdsaWinitem); i++) { WINITEM wi;
if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1) { if (wi.hwnd == hwnd) { if (DSA_DeleteItem(_hdsaWinitem, i) != -1) { *pwi = wi; fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: _DeleteWinitemByHwnd could note delete an item"); }
break; } } else { TraceMsg(TF_WARNING, "IEDDE: _DeleteWinitemByHwnd could note get an item"); } } } else { TraceMsg(TF_WARNING, "IEDDE: _DeleteWinitemByHwnd has no _hdsaWinitem"); }
LEAVE_IEDDE_CRIT;
EXITPROC(2, TEXT("_DeleteWinitemByHwnd=%d"), fSuccess); return fSuccess; }
//
// _NewWindow - Add a browser window to the internal list
//
BOOL CIEDDE::_NewWindow(HWND hwnd) { BOOL fSuccess = FALSE;
ENTERPROC(1, TEXT("NewWindow(hwnd=%08X)"), hwnd);
ASSERT(IS_VALID_HANDLE(hwnd, WND));
ENTER_IEDDE_CRIT;
WINITEM wi; if (GetWinitemFromHwnd(hwnd, &wi) == FALSE) { CIEDDEThread *pidt = new CIEDDEThread();
if (pidt) { DDETHREADINFO dti = {0}; DWORD dwThreadID = GetCurrentThreadId(); WINITEM wi; BOOL fCreatedDTI = FALSE;
if (_GetWinitemFromThread(dwThreadID, &wi)) { wi.pidt->GetDdeThreadInfo(&dti); } else { LEAVE_IEDDE_CRIT; _CreateDdeThreadInfo(&dti); ENTER_IEDDE_CRIT; fCreatedDTI = TRUE; }
if (dti.dwDDEInst) { static DWORD dwNextWindowID = 1;
pidt->SetDdeThreadInfo(&dti);
wi.dwThreadID = dwThreadID; wi.pidt = pidt; wi.hwnd = hwnd; wi.dwWindowID = dwNextWindowID++;
if (_AddWinitem(&wi)) { //
// Now that we have a (partial) winitem in the winitem
// database, we can register our name service. If we
// registered any sooner, there is a risk that an app
// will try to connect to us while we are registering,
// and we will fail the connect because the winitem
// is not in the registry yet.
//
LEAVE_IEDDE_CRIT; dti.hddNameService = DdeNameService(dti.dwDDEInst, dti.hszService, 0, DNS_REGISTER); ENTER_IEDDE_CRIT;
//
// Now that we have hddNameService, we can update the
// winitem in the database.
//
if (dti.hddNameService) { pidt->SetDdeThreadInfo(&dti); if (_UpdateWinitem(&wi)) { fSuccess = TRUE; } else { TraceMsg(TF_WARNING, "IEDDE: _NewWindow unable to update a win item"); } } else { TraceMsg(TF_WARNING, "IEDDE: _NewWindow unable to register service"); } } else { TraceMsg(TF_WARNING, "IEDDE: _NewWindow could not append win item"); }
if (!fSuccess && fCreatedDTI) { LEAVE_IEDDE_CRIT; _DestroyDdeThreadInfo(&dti); ENTER_IEDDE_CRIT; } } else { TraceMsg(TF_WARNING, "IEDDE: _NewWindow could not get/create dde thread info"); }
if (!fSuccess) { delete pidt; } } else { TraceMsg(TF_WARNING, "IEDDE: _NewWindow could not create iedde thread object"); } } else { TraceMsg(TF_WARNING, "IEDDE: _NewWindow says window already registered?!?"); }
LEAVE_IEDDE_CRIT;
EXITPROC(1, TEXT("_NewWindow=%d"), fSuccess); return fSuccess; }
//
// _WindowDestroyed - Remove a browser window from the internal list
//
BOOL CIEDDE::_WindowDestroyed(HWND hwnd) { BOOL fSuccess = FALSE; ENTERPROC(1, TEXT("_WindowDestroyed(hwnd=%08X)"), hwnd);
ENTER_IEDDE_CRIT;
WINITEM wi; if (_DeleteWinitemByHwnd(hwnd, &wi)) { fSuccess = TRUE;
ASSERT(wi.pidt); WINITEM wiThread;
if (_GetWinitemFromThread(wi.dwThreadID, &wiThread) == FALSE) { if (wi.dwThreadID == GetCurrentThreadId()) { DDETHREADINFO dti;
wi.pidt->GetDdeThreadInfo(&dti); // Don't hold onto critical section while doing this...
LEAVE_IEDDE_CRIT; _DestroyDdeThreadInfo(&dti); ENTER_IEDDE_CRIT; } else { TraceMsg(TF_WARNING, "IEDDE: _WindowDestroyed called on wrong thread"); } }
delete wi.pidt; } else { TraceMsg(TF_WARNING, "IEDDE: _WindowDestroyed could not find hwnd"); }
LEAVE_IEDDE_CRIT;
EXITPROC(1, TEXT("_WindowDestroyed=%d"), fSuccess); return fSuccess; }
//
// IEDDE_ functions are those exported for other parts of shdocvw to call.
// They pretty much just call the equivalent function in g_pIEDDE.
//
BOOL IEDDE_Initialize(void) { BOOL fRet = FALSE;
ENTERPROC(2, TEXT("IEDDE_Initialize()"));
if (g_pIEDDE == NULL) { g_pIEDDE = new CIEDDE;
if (g_pIEDDE) { fRet = g_pIEDDE->_Initialize(); } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_Initialize could not allocate an IEDDE object"); } } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_Initialize says already initialized"); }
EXITPROC(2, TEXT("IEDDE_Initialize=%d"), fRet); return fRet; }
void IEDDE_Uninitialize(void) { ENTERPROC(2, TEXT("IEDDE_Uninitialize()"));
if (g_pIEDDE) { g_pIEDDE->_Uninitialize(); delete g_pIEDDE; g_pIEDDE = NULL; } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_Uninitialize has no IEDDE object"); }
EXITPROC(2, TEXT("IEDDE_Uninitialize!")); }
BOOL IEDDE_RunDelayedExecute() { if (g_pIEDDE) { g_pIEDDE->RunDelayedExecute(); } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_RunDelayedExecute has no IEDDE object"); } return TRUE; }
void IEDDE_AutomationStarted(void) { ENTERPROC(2, TEXT("IEDDE_AutomationStarted()"));
if (g_pIEDDE) { g_pIEDDE->_AutomationStarted(); } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_AutomationStarted has no IEDDE object"); }
EXITPROC(2, TEXT("IEDDE_AutomationStarted!")); }
HRESULT IEDDE_BeforeNavigate(LPCWSTR pwszURL, BOOL *pfCanceled) { HRESULT hr = E_FAIL;
ENTERPROC(2, TEXT("IEDDE_BeforeNavigate(pwszURL=%08X,pfCanceled=%08X)"), pwszURL, pfCanceled);
if (g_pIEDDE) { LPCTSTR pszURL;
pszURL = pwszURL;
if (pszURL) { hr = g_pIEDDE->_BeforeNavigate(pszURL, pfCanceled); } } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_BeforeNavigate has no IEDDE object"); }
EXITPROC(2, TEXT("IEDDE_BeforeNavigate=%08X"), hr); return hr; }
HRESULT IEDDE_AfterNavigate(LPCWSTR pwszURL, HWND hwnd) { HRESULT hr = E_FAIL;
ENTERPROC(2, TEXT("IEDDE_AfterNavigate(pwszURL=%08X,hwnd=%08X)"), pwszURL, hwnd);
if (g_pIEDDE) { LPCTSTR pszURL;
pszURL = pwszURL;
if (pszURL) { hr = g_pIEDDE->_AfterNavigate(pszURL, hwnd); } } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_AfterNavigate has no IEDDE object"); }
EXITPROC(2, TEXT("IEDDE_AfterNavigate=%08X"), hr); return hr; }
BOOL IEDDE_NewWindow(HWND hwnd) { BOOL fRet = FALSE;
ENTERPROC(2, TEXT("IEDDE_NewWindow(hwnd=%08X)"), hwnd);
if (g_pIEDDE) { fRet = g_pIEDDE->_NewWindow(hwnd); } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_NewWindow has no IEDDE object"); }
EXITPROC(2, TEXT("IEDDE_NewWindow=%d"), fRet); return fRet; }
BOOL IEDDE_WindowDestroyed(HWND hwnd) { BOOL fRet = FALSE;
ENTERPROC(2, TEXT("IEDDE_WindowDestroyed(hwnd=%08X)"), hwnd);
if (g_pIEDDE) { fRet = g_pIEDDE->_WindowDestroyed(hwnd); } else { TraceMsg(TF_WARNING, "IEDDE: IEDDE_WindowDestroyed has no IEDDE object"); }
EXITPROC(2, TEXT("IEDDE_WindowDestroyed=%d"), fRet); return fRet; }
#ifdef DEBUG
//
// Move g_dwIEDDETrace into ccshell.ini to prevent recompiles.
//
DWORD g_dwIEDDETrace = 0; static DWORD g_dwIndent = 0; static const TCHAR c_szDotDot[] = TEXT("..");
#define MAX_INDENTATION_VALUE 0x10
void EnterProc(DWORD dwTraceLevel, LPTSTR szFmt, ...) { TCHAR szOutput[1000]; va_list arglist;
if (dwTraceLevel <= g_dwIEDDETrace) { szOutput[0] = TEXT('\0');
for (DWORD i=0; i<g_dwIndent; i++) { StrCatBuff(szOutput, c_szDotDot, ARRAYSIZE(szOutput)); }
va_start(arglist, szFmt); wvnsprintf(szOutput + lstrlen(szOutput), ARRAYSIZE(szOutput) - lstrlen(szOutput), szFmt, arglist); va_end(arglist);
TraceMsg(TF_ALWAYS, "%s", szOutput);
// This value can get out of hand if EnterProc and ExitProc
// calls do not match. This can trash the stack.
if(g_dwIndent < MAX_INDENTATION_VALUE) g_dwIndent++; } }
void ExitProc(DWORD dwTraceLevel, LPTSTR szFmt, ...) { TCHAR szOutput[1000]; va_list arglist;
if (dwTraceLevel <= g_dwIEDDETrace) { // This can happen if the EnterProc and
// ExitProc calls do not match.
if(g_dwIndent > 0) g_dwIndent--;
szOutput[0] = TEXT('\0');
for (DWORD i=0; i<g_dwIndent; i++) { StrCatBuff(szOutput, c_szDotDot, ARRAYSIZE(szOutput)); }
va_start(arglist, szFmt); wvnsprintf(szOutput + lstrlen(szOutput), ARRAYSIZE(szOutput) - lstrlen(szOutput), szFmt, arglist); va_end(arglist);
TraceMsg(TF_ALWAYS, "%s", szOutput); } }
#endif
|