Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

2840 lines
75 KiB

  1. /* Copyright 1996 Microsoft */
  2. #include "priv.h"
  3. #ifdef DEBUG
  4. #define ENTERPROC EnterProc
  5. #define EXITPROC ExitProc
  6. void EnterProc(DWORD dwTraceLevel, LPTSTR szFmt, ...);
  7. void ExitProc(DWORD dwTraceLevel, LPTSTR szFmt, ...);
  8. extern DWORD g_dwIEDDETrace;
  9. #else
  10. #pragma warning(disable:4002)
  11. #ifndef UNIX
  12. #ifndef CCOVER
  13. #define ENTERPROC()
  14. #define EXITPROC()
  15. #else //CCOVER
  16. // these are needed because of a bug in cl.exe which causes
  17. // compilation problems with #pragma when a program is preprocessed
  18. // and compiled separately
  19. #define ENTERPROC 1 ? (void) 0 : (void)
  20. #define EXITPROC 1 ? (void) 0 : (void)
  21. #endif // CCOVER
  22. #else
  23. #define ENTERPROC EnterProc
  24. #define EXITPROC ExitProc
  25. inline void EnterProc(DWORD dwTraceLevel, LPTSTR szFmt, ...){}
  26. inline void ExitProc(DWORD dwTraceLevel, LPTSTR szFmt, ...){}
  27. #endif
  28. #endif
  29. //
  30. // Forward reference.
  31. //
  32. class CIEDDEThread;
  33. //
  34. // Stored in _hdsaWinitem
  35. //
  36. typedef struct _tagWinItem
  37. {
  38. DWORD dwWindowID; // Synthetic window ID exposed in IEDDE interfaces
  39. HWND hwnd; // Actual hwnd of browser window
  40. DWORD dwThreadID; // ThreadID for this browser window
  41. CIEDDEThread *pidt; // Thread specific data and methods
  42. } WINITEM;
  43. //
  44. // Stored in _hdsaProtocolHandler
  45. //
  46. typedef struct _tagProtocolReg
  47. {
  48. LPTSTR pszProtocol;
  49. LPTSTR pszServer;
  50. } PROTOCOLREG;
  51. #define TEN_SECONDS (10 * 1000)
  52. #define DXA_GROWTH_AMOUNT (10)
  53. #ifndef UNIX
  54. #define IEXPLORE_STR "IEXPLORE"
  55. #else
  56. #define IEXPLORE_STR "iexplorer"
  57. #endif
  58. static const TCHAR c_szIExplore[] = TEXT(IEXPLORE_STR);
  59. static const TCHAR c_szReturn[] = TEXT("Return");
  60. static const TCHAR c_szWWWOpenURL[] = TEXT("WWW_OpenURL");
  61. static const TCHAR c_szWWWUrlEcho[] = TEXT("WWW_URLEcho");
  62. typedef struct _tagDDETHREADINFO
  63. {
  64. DWORD dwDDEInst;
  65. HSZ hszService;
  66. HSZ hszReturn;
  67. HDDEDATA hddNameService;
  68. } DDETHREADINFO;
  69. class CIEDDEThread {
  70. public:
  71. CIEDDEThread() { };
  72. ~CIEDDEThread() { };
  73. void GetDdeThreadInfo(DDETHREADINFO *pdti) { *pdti = _dti; }
  74. void SetDdeThreadInfo(DDETHREADINFO *pdti) { _dti = *pdti; }
  75. HDDEDATA OnRequestPoke(HSZ hszTopic, HSZ hszParams);
  76. HDDEDATA OnExecute(HSZ hszTopic, HDDEDATA hddParams);
  77. HDDEDATA CallTopic(DWORD dwType, LPCTSTR pszTopic, LPTSTR pszParams);
  78. protected:
  79. DDETHREADINFO _dti;
  80. HDDEDATA DoNavigate(LPTSTR pszLocation, HWND hwnd, BOOL bLaunchNewWindow);
  81. BOOL MakeQuotedString(LPCTSTR pszInput, LPTSTR pszOutput, int cchOutput);
  82. HDDEDATA CreateReturnObject(LPVOID p, DWORD cb);
  83. HDDEDATA CreateReturnStringObject(LPTSTR pszReturnString, DWORD cch);
  84. BOOL ParseString(LPTSTR *ppsz, LPTSTR *ppszString);
  85. BOOL ParseQString(LPTSTR *ppsz, LPTSTR *ppszString);
  86. BOOL ParseNumber(LPTSTR *ppsz, DWORD *pdw);
  87. BOOL ParseWinitem(LPTSTR *ppsz, WINITEM *pwi);
  88. HDDEDATA WWW_GetWindowInfo(LPTSTR pszParams);
  89. HDDEDATA WWW_OpenURL(LPTSTR pszParams);
  90. HDDEDATA WWW_OpenURLNewWindow(LPTSTR pszParams);
  91. HDDEDATA WWW_ShowFile(LPTSTR pszParams);
  92. HDDEDATA WWW_Activate(LPTSTR pszParams);
  93. HDDEDATA WWW_Exit(LPTSTR pszParams);
  94. HDDEDATA WWW_RegisterURLEcho(LPTSTR pszParams);
  95. HDDEDATA WWW_UnregisterURLEcho(LPTSTR pszParams);
  96. HDDEDATA WWW_RegisterProtocol(LPTSTR pszParams);
  97. HDDEDATA WWW_UnregisterProtocol(LPTSTR pszParams);
  98. HDDEDATA WWW_ListWindows(LPTSTR pszParams);
  99. };
  100. class CIEDDE {
  101. public:
  102. CIEDDE() { };
  103. ~CIEDDE() { };
  104. BOOL IsAutomationReady(void) { return _fAutomationReady; }
  105. BOOL GetWinitemFromWindowID(DWORD dwWindowID, WINITEM *pwi);
  106. BOOL GetWinitemFromHwnd(HWND hwnd, WINITEM *pwi);
  107. BOOL AddUrlEcho(LPCTSTR pszUrlEcho);
  108. BOOL RemoveUrlEcho(LPCTSTR pszUrlEcho);
  109. BOOL AddProtocolHandler(LPCTSTR pszServer, LPCTSTR pszProtocol);
  110. BOOL RemoveProtocolHandler(LPCTSTR pszServer, LPCTSTR pszProtocol);
  111. HDSA GetHdsaWinitem(void) { return _hdsaWinitem; }
  112. static HDDEDATA DdeCallback(UINT dwType, UINT dwFmt, HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hdd, DWORD dwData1, DWORD dwData2);
  113. void EnterCrit(void) { ASSERT(_fCSInitialized); EnterCriticalSection(&_csIEDDE); }
  114. void LeaveCrit(void) { ASSERT(_fCSInitialized); LeaveCriticalSection(&_csIEDDE); }
  115. void SetDelayedExecute(LPCTSTR pszTopic, LPCTSTR pszParams);
  116. void RunDelayedExecute();
  117. protected:
  118. BOOL _fAutomationReady;
  119. HDSA _hdsaWinitem;
  120. HDSA _hdsaProtocolHandler;
  121. HDPA _hdpaUrlEcho;
  122. BOOL _fCSInitialized;
  123. CRITICAL_SECTION _csIEDDE;
  124. DWORD _dwThreadID;
  125. LPTSTR _pszTopic;
  126. LPTSTR _pszParams;
  127. HDDEDATA _SendDDEMessageHsz(DWORD dwDDEInst, HSZ hszApp, HSZ hszTopic, HSZ hszMessage, UINT wType);
  128. HDDEDATA _SendDDEMessageSz(DWORD dwDDEInst, LPCTSTR pszApp, LPCTSTR pszTopic, LPCTSTR pszMessage, UINT wType);
  129. static int _DestroyProtocol(LPVOID p1, LPVOID p2);
  130. static int _DestroyUrlEcho(LPVOID p1, LPVOID p2);
  131. static int _DestroyWinitem(LPVOID p1, LPVOID p2);
  132. BOOL _GetWinitemFromThread(DWORD dwThreadID, WINITEM *pwi);
  133. BOOL _GetDtiFromThread(DWORD dwThreadID, DDETHREADINFO *pdti);
  134. BOOL _CreateDdeThreadInfo(DDETHREADINFO *pdti);
  135. void _DestroyDdeThreadInfo(DDETHREADINFO *pdti);
  136. BOOL _AddWinitem(WINITEM *pwi);
  137. BOOL _UpdateWinitem(WINITEM *pwi);
  138. BOOL _DeleteWinitemByHwnd(HWND hwnd, WINITEM *pwi);
  139. BOOL _Initialize(void);
  140. void _Uninitialize(void);
  141. void _AutomationStarted(void);
  142. HRESULT _BeforeNavigate(LPCTSTR pszURL, BOOL *pfProcessed);
  143. HRESULT _AfterNavigate(LPCTSTR pszURL, HWND hwnd);
  144. BOOL _NewWindow(HWND hwnd);
  145. BOOL _WindowDestroyed(HWND hwnd);
  146. friend BOOL IEDDE_Initialize(void);
  147. friend void IEDDE_Uninitialize(void);
  148. friend void IEDDE_AutomationStarted(void);
  149. friend HRESULT IEDDE_BeforeNavigate(LPCWSTR pwszURL, BOOL *pfProcessed);
  150. friend HRESULT IEDDE_AfterNavigate(LPCWSTR pwszURL, HWND hwnd);
  151. friend BOOL IEDDE_NewWindow(HWND hwnd);
  152. friend BOOL IEDDE_WindowDestroyed(HWND hwnd);
  153. };
  154. CIEDDE *g_pIEDDE = NULL;
  155. #define ENTER_IEDDE_CRIT g_pIEDDE->EnterCrit()
  156. #define LEAVE_IEDDE_CRIT g_pIEDDE->LeaveCrit()
  157. //
  158. // There is one CIEDDEThread object per browser window.
  159. // Its private data consists of DDE handles, which are
  160. // necessarily valid only in the thread that created them.
  161. //
  162. // Its methods consist of three broad categories:
  163. // the parser
  164. // the dispatcher
  165. // one handler for each DDE topic
  166. //
  167. //
  168. // CreateReturnObject - creates a dde data item.
  169. //
  170. #define CREATE_HDD(x) CreateReturnObject(&x, SIZEOF(x))
  171. HDDEDATA CIEDDEThread::CreateReturnObject(LPVOID p, DWORD cb)
  172. {
  173. HDDEDATA hddRet;
  174. ENTERPROC(2, TEXT("CreateReturnObject(p=%08X,cb=%d)"), p, cb);
  175. hddRet = DdeCreateDataHandle(_dti.dwDDEInst, (BYTE *)p, cb, 0, _dti.hszReturn, CF_TEXT, 0);
  176. if (hddRet == 0)
  177. {
  178. TraceMsg(TF_WARNING, "IEDDE: Could not create return object");
  179. }
  180. EXITPROC(2, TEXT("CreateReturnObject=%08X"), hddRet);
  181. return hddRet;
  182. }
  183. HDDEDATA CIEDDEThread::CreateReturnStringObject(LPTSTR pszReturnString, DWORD cch)
  184. {
  185. HDDEDATA hddRet = 0;
  186. ENTERPROC(2, TEXT("CreateReturnStringObject(p=%s,cb=%d)"), pszReturnString, cch);
  187. //
  188. // REVIEW I thought specifying CF_UNICODETEXT should have worked, but...
  189. // it didn't, so always return ANSI string as out string params
  190. // - julianj
  191. //
  192. LPSTR pszAnsiBuf = (LPSTR)LocalAlloc(LPTR, cch+1);
  193. if (pszAnsiBuf)
  194. {
  195. SHUnicodeToAnsi(pszReturnString, pszAnsiBuf, cch+1);
  196. hddRet = DdeCreateDataHandle(_dti.dwDDEInst, (BYTE *)pszAnsiBuf, (cch+1), 0, _dti.hszReturn, CF_TEXT, 0);
  197. LocalFree(pszAnsiBuf);
  198. pszAnsiBuf = NULL;
  199. }
  200. if (hddRet == 0)
  201. {
  202. TraceMsg(TF_WARNING, "IEDDE: Could not create return object");
  203. }
  204. EXITPROC(2, TEXT("CreateReturnObject=%08X"), hddRet);
  205. return hddRet;
  206. }
  207. //
  208. // OnRequestPoke - handle XTYP_REQUEST and XTYP_POKE
  209. //
  210. HDDEDATA CIEDDEThread::OnRequestPoke(HSZ hszTopic, HSZ hszParams)
  211. {
  212. HDDEDATA hddRet = 0;
  213. ENTERPROC(2, TEXT("OnRequestPoke(hszTopic=%08X,hszParams=%08X)"), hszTopic, hszParams);
  214. TCHAR szTopic[100];
  215. TCHAR szParams[1000];
  216. if (DdeQueryString(_dti.dwDDEInst, hszTopic, szTopic, ARRAYSIZE(szTopic), CP_WINNEUTRAL) != 0)
  217. {
  218. if (DdeQueryString(_dti.dwDDEInst, hszParams, szParams, ARRAYSIZE(szParams), CP_WINNEUTRAL))
  219. {
  220. hddRet = CallTopic(XTYP_REQUEST, szTopic, szParams);
  221. }
  222. else
  223. {
  224. TraceMsg(TF_WARNING, "IEDDE: OnRequestPoke could not query the parameters");
  225. }
  226. }
  227. else
  228. {
  229. TraceMsg(TF_WARNING, "IEDDE: OnRequestPoke could not query the topic");
  230. }
  231. EXITPROC(2, TEXT("OnRequestPoke=%08X"), hddRet);
  232. return hddRet;
  233. }
  234. //
  235. // OnExecute - handle XTYP_EXECUTE
  236. //
  237. HDDEDATA CIEDDEThread::OnExecute(HSZ hszTopic, HDDEDATA hddParams)
  238. {
  239. HDDEDATA hddRet = 0;
  240. ENTERPROC(2, TEXT("OnExecute(hszTopic=%08X,hddParams=%08X)"), hszTopic, hddParams);
  241. TCHAR szTopic[100];
  242. if (DdeQueryString(_dti.dwDDEInst, hszTopic, szTopic, ARRAYSIZE(szTopic), CP_WINNEUTRAL) != 0)
  243. {
  244. //
  245. // Why "cbParams + 3"?
  246. // UNICODE - if we cut the last unicode character in half, we need
  247. // one 0 to finish the character, and two more 0 for the
  248. // terminating NULL
  249. // ANSI - if we cut the last DBCS character in half, we need one 0
  250. // to finish the character, and one 0 for the terminating NULL
  251. //
  252. //
  253. DWORD cbParams = DdeGetData(hddParams, NULL, 0, 0) + 3;
  254. LPTSTR pszParams = (LPTSTR) LocalAlloc(LPTR, cbParams);
  255. if(pszParams)
  256. {
  257. DdeGetData(hddParams, (BYTE *)pszParams, cbParams, 0);
  258. //
  259. // DdeGetData can't be wrapped in shlwapi since it can return non
  260. // string data. Here we only expect strings so the result can be
  261. // safely converted.
  262. //
  263. if (g_fRunningOnNT)
  264. {
  265. hddRet = CallTopic(XTYP_EXECUTE, szTopic, pszParams);
  266. }
  267. else
  268. {
  269. WCHAR szParams[MAX_URL_STRING];
  270. SHAnsiToUnicode((LPCSTR)pszParams, szParams, ARRAYSIZE(szParams));
  271. hddRet = CallTopic(XTYP_EXECUTE, szTopic, szParams);
  272. }
  273. LocalFree(pszParams);
  274. pszParams = NULL;
  275. }
  276. else
  277. {
  278. TraceMsg(TF_WARNING, "IEDDE: OnExecute could not query the topic");
  279. }
  280. }
  281. else
  282. {
  283. TraceMsg(TF_WARNING, "IEDDE: OnExecute could not query the topic");
  284. }
  285. EXITPROC(2, TEXT("OnExecute=%08X"), hddRet);
  286. return hddRet;
  287. }
  288. //
  289. // CallTopic - Looks up the command in the DDETOPICHANDLER table and calls the
  290. // corresponding function.
  291. //
  292. HDDEDATA CIEDDEThread::CallTopic(DWORD dwType, LPCTSTR pszTopic, LPTSTR pszParams)
  293. {
  294. HDDEDATA hddRet = DDE_FNOTPROCESSED;
  295. ENTERPROC(2, TEXT("CallTopic(wType=%d,pszTopic=>%s<,pszParams=>%s<)"), dwType, pszTopic, pszParams);
  296. #define DISPATCH_BEGIN
  297. #define DISPATCH(topic) \
  298. if (StrCmpI(TEXT("WWW_") TEXT(#topic), pszTopic) == 0) \
  299. { \
  300. if (fCanRun) \
  301. { \
  302. hddRet = WWW_ ## topic(pszParams); \
  303. } \
  304. else \
  305. { \
  306. fAbortedRun = TRUE; \
  307. } \
  308. } \
  309. else
  310. #define DISPATCH_END { TraceMsg(TF_WARNING, "IEDDE: CallTopic given unknown topic"); }
  311. BOOL fAbortedRun = FALSE;
  312. BOOL fCanRun = ((dwType != XTYP_EXECUTE) || g_pIEDDE->IsAutomationReady());
  313. DISPATCH_BEGIN
  314. DISPATCH(GetWindowInfo)
  315. DISPATCH(OpenURL)
  316. DISPATCH(ShowFile)
  317. DISPATCH(Activate)
  318. DISPATCH(Exit)
  319. DISPATCH(RegisterURLEcho)
  320. DISPATCH(UnregisterURLEcho)
  321. DISPATCH(RegisterProtocol)
  322. DISPATCH(UnregisterProtocol)
  323. DISPATCH(ListWindows)
  324. DISPATCH(OpenURLNewWindow)
  325. DISPATCH_END
  326. if (fAbortedRun)
  327. {
  328. if (dwType == XTYP_EXECUTE)
  329. {
  330. g_pIEDDE->SetDelayedExecute(pszTopic, pszParams);
  331. }
  332. hddRet = (HDDEDATA)DDE_FACK;
  333. TraceMsg(TF_WARNING, "IEDDE: CallTopic received XTYP_EXECUTE before Automation was ready - not processing");
  334. }
  335. EXITPROC(2, TEXT("CallTopic=%08X"), hddRet);
  336. return hddRet;
  337. }
  338. //
  339. // ParseString - parse one string
  340. //
  341. BOOL CIEDDEThread::ParseString(LPTSTR *ppsz, LPTSTR *ppszString)
  342. {
  343. BOOL fRet = FALSE;
  344. ENTERPROC(3, TEXT("ParseString(ppsz=%08X,ppszString=%08X)"), ppsz, ppszString);
  345. LPTSTR pchCurrent, pchNext;
  346. BOOL fInQuote = FALSE;
  347. pchCurrent = pchNext = *ppsz;
  348. while (*pchNext)
  349. {
  350. switch (*pchNext)
  351. {
  352. case TEXT(' '):
  353. case TEXT('\t'):
  354. if (fInQuote)
  355. {
  356. //
  357. // Skip over whitespace when not inside quotes.
  358. //
  359. *pchCurrent++ = *pchNext;
  360. }
  361. pchNext++;
  362. break;
  363. case TEXT('"'):
  364. //
  365. // Always copy quote marks.
  366. //
  367. fInQuote = !fInQuote;
  368. *pchCurrent++ = *pchNext++;
  369. break;
  370. case TEXT(','):
  371. if (!fInQuote)
  372. {
  373. goto done_parsing;
  374. }
  375. *pchCurrent++ = *pchNext++;
  376. break;
  377. case TEXT('\\'):
  378. if (fInQuote &&
  379. (*(pchNext+1) == TEXT('"')))
  380. {
  381. //
  382. // When in quotes, a \" becomes a ".
  383. //
  384. pchNext++;
  385. }
  386. *pchCurrent++ = *pchNext++;
  387. break;
  388. default:
  389. *pchCurrent++ = *pchNext++;
  390. break;
  391. }
  392. }
  393. done_parsing:
  394. //
  395. // Advance past the comma separator.
  396. //
  397. if (*pchNext == TEXT(','))
  398. {
  399. pchNext++;
  400. }
  401. //
  402. // NULL terminate the return string.
  403. //
  404. *pchCurrent = TEXT('\0');
  405. //
  406. // Set the return values.
  407. //
  408. *ppszString = *ppsz;
  409. *ppsz = pchNext;
  410. fRet = TRUE;
  411. EXITPROC(3, TEXT("ParseString=%d"), fRet);
  412. return fRet;
  413. }
  414. //
  415. // ParseQString - parse one quoted string
  416. //
  417. BOOL CIEDDEThread::ParseQString(LPTSTR *ppsz, LPTSTR *ppszString)
  418. {
  419. BOOL fRet = FALSE;
  420. ENTERPROC(3, TEXT("ParseQString(ppsz=%08X,ppszString=%08X)"), ppsz, ppszString);
  421. if (ParseString(ppsz, ppszString))
  422. {
  423. LPTSTR pszString = *ppszString;
  424. int cch = lstrlen(pszString);
  425. //
  426. // Strip off optional outer quotes.
  427. //
  428. if ((cch >= 2) &&
  429. (pszString[0] == TEXT('"')) &&
  430. (pszString[cch-1] == TEXT('"')))
  431. {
  432. pszString[0] = pszString[cch-1] = TEXT('\0');
  433. *ppszString = pszString + 1;
  434. }
  435. fRet = TRUE;
  436. }
  437. EXITPROC(3, TEXT("ParseQString=%d"), fRet);
  438. return fRet;
  439. }
  440. //
  441. // ParseNumber - parse one numeric value
  442. //
  443. BOOL CIEDDEThread::ParseNumber(LPTSTR *ppsz, DWORD *pdw)
  444. {
  445. BOOL fRet = FALSE;
  446. LPTSTR pszNumber;
  447. ENTERPROC(3, TEXT("GetNumber(ppsz=%08X,pdw=%08X)"), ppsz, pdw);
  448. if (ParseString(ppsz, &pszNumber) && pszNumber[0])
  449. {
  450. StrToIntEx(pszNumber, STIF_SUPPORT_HEX, (int *)pdw);
  451. fRet = TRUE;
  452. }
  453. EXITPROC(3, TEXT("GetNumber=%d"), fRet);
  454. return fRet;
  455. }
  456. //
  457. // ParseWinitem - parse one window ID, and return the winitem
  458. //
  459. BOOL CIEDDEThread::ParseWinitem(LPTSTR *ppsz, WINITEM *pwi)
  460. {
  461. BOOL fRet = FALSE;
  462. DWORD dwWindowID;
  463. ENTERPROC(3, TEXT("ParseWinitem(ppsz=%08X,pwi=%08X)"), ppsz, pwi);
  464. if (ParseNumber(ppsz, &dwWindowID))
  465. {
  466. switch (dwWindowID)
  467. {
  468. case 0:
  469. case -1:
  470. ZeroMemory(pwi, SIZEOF(*pwi));
  471. pwi->dwWindowID = dwWindowID;
  472. pwi->hwnd = (HWND)LongToHandle(dwWindowID);
  473. fRet = TRUE;
  474. break;
  475. default:
  476. fRet = g_pIEDDE->GetWinitemFromWindowID(dwWindowID, pwi);
  477. break;
  478. }
  479. }
  480. EXITPROC(3, TEXT("ParseWinitem=%d"), fRet);
  481. return fRet;
  482. }
  483. //
  484. // WWW_GetWindowInfo - get information about a browser window
  485. //
  486. // Parameters:
  487. // dwWindowID - Window ID to examine (-1 = last active window)
  488. //
  489. // Returns:
  490. // qcsURL,qcsTitle
  491. //
  492. HDDEDATA CIEDDEThread::WWW_GetWindowInfo(LPTSTR pszParams)
  493. {
  494. HDDEDATA hddRet = 0;
  495. WINITEM wi;
  496. ENTERPROC(1, TEXT("WWW_GetWindowInfo(pszParams=>%s<)"), pszParams);
  497. if (ParseWinitem(&pszParams, &wi) &&
  498. (wi.hwnd != 0))
  499. {
  500. BSTR bstrURL;
  501. if (SUCCEEDED(CDDEAuto_get_LocationURL(&bstrURL, wi.hwnd)) && (bstrURL != (BSTR)-1))
  502. {
  503. BSTR bstrTitle;
  504. if (SUCCEEDED(CDDEAuto_get_LocationTitle(&bstrTitle, wi.hwnd)) && (bstrTitle != (BSTR)-1))
  505. {
  506. LPTSTR pszURL, pszTitle;
  507. pszURL = bstrURL;
  508. pszTitle = bstrTitle;
  509. if (pszURL && pszTitle)
  510. {
  511. TCHAR szURLQ[MAX_URL_STRING];
  512. TCHAR szTitleQ[MAX_URL_STRING];
  513. if (MakeQuotedString(pszURL, szURLQ, ARRAYSIZE(szURLQ)) &&
  514. MakeQuotedString(pszTitle, szTitleQ, ARRAYSIZE(szTitleQ)))
  515. {
  516. DWORD cchBuffer = lstrlen(szURLQ) + 1 + lstrlen(szTitleQ) + 1;
  517. LPTSTR pszBuffer = (LPTSTR)LocalAlloc(LPTR, cchBuffer * SIZEOF(TCHAR));
  518. if (pszBuffer)
  519. {
  520. wnsprintf(pszBuffer, cchBuffer, TEXT("%s,%s"), szURLQ, szTitleQ);
  521. hddRet = CreateReturnStringObject(pszBuffer, lstrlen(pszBuffer));
  522. LocalFree(pszBuffer);
  523. pszBuffer = NULL;
  524. }
  525. else
  526. {
  527. TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not alloc buffer");
  528. }
  529. }
  530. else
  531. {
  532. TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not quote return strings");
  533. }
  534. }
  535. SysFreeString(bstrTitle);
  536. }
  537. else
  538. {
  539. TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not get title");
  540. }
  541. SysFreeString(bstrURL);
  542. }
  543. else
  544. {
  545. TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not get URL");
  546. }
  547. }
  548. else
  549. {
  550. TraceMsg(TF_WARNING, "IEDDE: GetWindowInfo could not parse parameters");
  551. }
  552. EXITPROC(1, TEXT("WWW_GetWindowInfo=%08X"), hddRet);
  553. return hddRet;
  554. }
  555. //
  556. // WWW_OpenURLNewWindow - navigate to a URL (but make sure to spawn a new window)
  557. //
  558. // NOTE: this code was stolen from IEDDEThread::WWW_OpenURL below
  559. //
  560. HDDEDATA CIEDDEThread::WWW_OpenURLNewWindow(LPTSTR pszParams)
  561. {
  562. HDDEDATA hddRet = 0;
  563. LPTSTR pszUrl, pszFile;
  564. ENTERPROC(1, TEXT("WWW_OpenURLNewWindow(pszParams=>%s<)"), pszParams);
  565. if (*pszParams == TEXT('\0') || *pszParams == TEXT('*'))
  566. {
  567. // An empty string is a NOOP.
  568. }
  569. else if (ParseQString(&pszParams, &pszUrl) &&
  570. ParseQString(&pszParams, &pszFile))
  571. {
  572. // null hwnd & bLaunchNewWindow = TRUE means "launch a new window",
  573. // which is exactly what we want to do in the WWW_OpenURLNewWindow case
  574. hddRet = DoNavigate(pszUrl, NULL, TRUE);
  575. }
  576. else
  577. {
  578. TraceMsg(TF_WARNING, "IEDDE: WWW_OpenURLNewWindow could not parse parameters");
  579. }
  580. EXITPROC(1, TEXT("WWW_OpenURL=%08X"), hddRet);
  581. return hddRet;
  582. }
  583. //
  584. // WWW_OpenURL - navigate to a URL
  585. //
  586. // Parameters:
  587. // qcsURL - url to navigate to
  588. // qcsSaveFile - [optional] file to save contents in
  589. // dwWindowID - Window ID to perform navigation
  590. // dwFlags - flags for navigation
  591. // qcsPostFormData - [optional] form data to post to URL
  592. // qcsPostMIMEType - [optional] mime type for form data
  593. // csProgressServer - [optional] DDE server to get progress updates
  594. //
  595. // Returns:
  596. // dwWindowID - window which is doing the work
  597. //
  598. HDDEDATA CIEDDEThread::WWW_OpenURL(LPTSTR pszParams)
  599. {
  600. HDDEDATA hddRet = 0;
  601. LPTSTR pszUrl, pszFile;
  602. WINITEM wi;
  603. ENTERPROC(1, TEXT("WWW_OpenURL(pszParams=>%s<)"), pszParams);
  604. if (*pszParams == TEXT('\0') || *pszParams == TEXT('*'))
  605. {
  606. // An empty string is a NOOP. Needed for NT #291766
  607. }
  608. else if (ParseQString(&pszParams, &pszUrl) &&
  609. ParseQString(&pszParams, &pszFile))
  610. {
  611. //
  612. // APPCOMPAT - a missing hwnd parameter implies -1.
  613. //
  614. if (!ParseWinitem(&pszParams, &wi))
  615. {
  616. TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required hwnd parameter to WWW_OpenURL, assuming -1");
  617. wi.hwnd = (HWND)-1;
  618. }
  619. #ifdef DEBUG
  620. DWORD dwFlags;
  621. if (!ParseNumber(&pszParams, &dwFlags))
  622. {
  623. TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required dwFlags parameter to WWW_OpenURL");
  624. }
  625. #endif
  626. hddRet = DoNavigate(pszUrl, wi.hwnd, FALSE);
  627. }
  628. else
  629. {
  630. TraceMsg(TF_WARNING, "IEDDE: OpenURL could not parse parameters");
  631. }
  632. EXITPROC(1, TEXT("WWW_OpenURL=%08X"), hddRet);
  633. return hddRet;
  634. }
  635. //
  636. // WWW_ShowFile - navigate to a file
  637. //
  638. // Parameters:
  639. // qcsFilename - file to load
  640. // qcsPostMIMEType - [optional] mime type for form data
  641. // dwWindowID - Window ID to perform navigation
  642. // qcsURL - URL of the same document
  643. //
  644. // Returns:
  645. // dwWindowID - window which is doing the work
  646. //
  647. HDDEDATA CIEDDEThread::WWW_ShowFile(LPTSTR pszParams)
  648. {
  649. HDDEDATA hddRet = 0;
  650. LPTSTR pszFilename, pszMIMEType;
  651. WINITEM wi;
  652. ENTERPROC(1, TEXT("WWW_ShowFile(pszParams=>%s<)"), pszParams);
  653. if (ParseQString(&pszParams, &pszFilename) && pszFilename[0])
  654. {
  655. if (!ParseQString(&pszParams, &pszMIMEType) || !pszMIMEType[0])
  656. {
  657. TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required MIMEType parameter to WWW_ShowFile");
  658. }
  659. if (!ParseWinitem(&pszParams, &wi))
  660. {
  661. TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required dwWindowID parameter to WWW_ShowFile, assuming -1");
  662. wi.hwnd = (HWND)-1;
  663. }
  664. #ifdef DEBUG
  665. LPTSTR pszURL;
  666. if (!ParseQString(&pszParams, &pszURL) || !pszURL[0])
  667. {
  668. TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required szURL parameter to WWW_ShowFile");
  669. }
  670. #endif
  671. hddRet = DoNavigate(pszFilename, wi.hwnd, FALSE);
  672. }
  673. else
  674. {
  675. TraceMsg(TF_WARNING, "IEDDE: ShowFile could not parse parameters");
  676. }
  677. EXITPROC(1, TEXT("WWW_ShowFile=%08X"), hddRet);
  678. return hddRet;
  679. }
  680. //
  681. // DoNavigate - navigate to a location
  682. //
  683. HDDEDATA CIEDDEThread::DoNavigate(LPTSTR pszLocation, HWND hwnd, BOOL bLaunchNewWindow)
  684. {
  685. HDDEDATA hddRet = 0;
  686. HRESULT hr = S_OK;
  687. TCHAR szParsedPath[MAX_URL_STRING+1];
  688. DWORD cchParsedPath = ARRAYSIZE(szParsedPath);
  689. ENTERPROC(2, TEXT("DoNavigate(pszLocation=>%s<,hwnd=%08X)"), pszLocation, hwnd);
  690. //
  691. // Convert URL from outside format to internal format.
  692. //
  693. if (ParseURLFromOutsideSource(pszLocation, szParsedPath, &cchParsedPath, NULL))
  694. {
  695. pszLocation = szParsedPath;
  696. }
  697. //
  698. // In the case of a file:// URL, convert the location to a path.
  699. //
  700. cchParsedPath = ARRAYSIZE(szParsedPath);
  701. if (IsFileUrlW(pszLocation) && SUCCEEDED(PathCreateFromUrl(pszLocation, szParsedPath, &cchParsedPath, 0)))
  702. {
  703. pszLocation = szParsedPath;
  704. }
  705. LPWSTR pwszPath;
  706. pwszPath = pszLocation;
  707. if (SUCCEEDED(hr))
  708. {
  709. hr = CDDEAuto_Navigate(pwszPath, &hwnd, bLaunchNewWindow ? 1 : 0);
  710. }
  711. DWORD dwServicingWindow = SUCCEEDED(hr) ? -2 : -3;
  712. hddRet = CREATE_HDD(dwServicingWindow);
  713. EXITPROC(2, TEXT("DoNavigate=%08X"), hddRet);
  714. return hddRet;
  715. }
  716. //
  717. // WWW_Activate - activate a browser window
  718. //
  719. // Parameters:
  720. // dwWindowID - Window ID to activate
  721. // dwFlags - should always zero
  722. //
  723. // Returns:
  724. // dwWindowID - window ID that got activated
  725. //
  726. HDDEDATA CIEDDEThread::WWW_Activate(LPTSTR pszParams)
  727. {
  728. HDDEDATA hddRet = 0;
  729. WINITEM wi;
  730. ENTERPROC(1, TEXT("WWW_Activate(pszParams=>%s<)"), pszParams);
  731. if (ParseWinitem(&pszParams, &wi) &&
  732. wi.dwWindowID != 0)
  733. {
  734. #ifdef DEBUG
  735. DWORD dwFlags;
  736. if (ParseNumber(&pszParams, &dwFlags))
  737. {
  738. //
  739. // Netscape spec says this should always be zero.
  740. //
  741. ASSERT(dwFlags == 0);
  742. }
  743. else
  744. {
  745. TraceMsg(TF_WARNING, "IEDDE: Some bozo isn't giving the required dwFlags parameter to WWW_Activate");
  746. }
  747. #endif
  748. //
  749. // dwWindowID of -1 means use the active window.
  750. //
  751. if (wi.dwWindowID == -1)
  752. {
  753. HWND hwnd;
  754. CDDEAuto_get_HWND((long *)&hwnd);
  755. if (hwnd)
  756. {
  757. if (g_pIEDDE->GetWinitemFromHwnd(hwnd, &wi) == FALSE)
  758. {
  759. wi.dwWindowID = (DWORD)-1;
  760. }
  761. }
  762. else
  763. {
  764. TraceMsg(TF_WARNING, "IEDDE: Activate could not find an active window");
  765. }
  766. }
  767. //
  768. // Activate the window.
  769. //
  770. if (wi.dwWindowID != -1)
  771. {
  772. if ((GetForegroundWindow() == wi.hwnd) || (SetForegroundWindow(wi.hwnd)))
  773. {
  774. if (IsIconic(wi.hwnd))
  775. {
  776. ShowWindow(wi.hwnd, SW_RESTORE);
  777. }
  778. }
  779. else
  780. {
  781. TraceMsg(TF_WARNING, "IEDDE: Activate could not set foreground window");
  782. }
  783. hddRet = CREATE_HDD(wi.dwWindowID);
  784. }
  785. else
  786. {
  787. TraceMsg(TF_WARNING, "IEDDE: Activate could not find a browser window to activate");
  788. }
  789. }
  790. else
  791. {
  792. TraceMsg(TF_WARNING, "IEDDE: Activate could not parse parameters");
  793. }
  794. EXITPROC(1, TEXT("WWW_Activate=%08X"), hddRet);
  795. return hddRet;
  796. }
  797. //
  798. // WWW_Exit - close all browser windows
  799. //
  800. // Parameters:
  801. // none
  802. //
  803. // Returns:
  804. // none
  805. //
  806. HDDEDATA CIEDDEThread::WWW_Exit(LPTSTR pszParams)
  807. {
  808. HDDEDATA hddRet = 0;
  809. ENTERPROC(1, TEXT("WWW_Exit(pszParams=>%s<)"), pszParams);
  810. CDDEAuto_Exit();
  811. EXITPROC(1, TEXT("WWW_Exit=%08X"), hddRet);
  812. return hddRet;
  813. }
  814. //
  815. // WWW_RegisterURLEcho - register a server for URL change notifications
  816. //
  817. // Parameters:
  818. // qcsServer - the DDE server to get notifications
  819. //
  820. // Returns:
  821. // fSuccess
  822. //
  823. HDDEDATA CIEDDEThread::WWW_RegisterURLEcho(LPTSTR pszParams)
  824. {
  825. HDDEDATA hddRet = 0;
  826. BOOL fSuccess = FALSE;
  827. LPTSTR pszServer;
  828. ENTERPROC(1, TEXT("WWW_RegisterURLEcho(pszParams=>%s<)"), pszParams);
  829. if (ParseQString(&pszParams, &pszServer) && pszServer[0])
  830. {
  831. LPTSTR pszServerCopy = StrDup(pszServer);
  832. if (pszServerCopy)
  833. {
  834. if (g_pIEDDE->AddUrlEcho(pszServerCopy))
  835. {
  836. fSuccess = TRUE;
  837. }
  838. else
  839. {
  840. TraceMsg(TF_WARNING, "IEDDE: RegisterURLEcho could not add an URLEcho");
  841. }
  842. if (!fSuccess)
  843. {
  844. LocalFree(pszServerCopy);
  845. pszServerCopy = NULL;
  846. }
  847. }
  848. else
  849. {
  850. TraceMsg(TF_WARNING, "IEDDE: RegisterURLEcho could not dup a string");
  851. }
  852. }
  853. else
  854. {
  855. TraceMsg(TF_WARNING, "IEDDE: RegisterURLEcho could not parse parameters");
  856. }
  857. hddRet = CREATE_HDD(fSuccess);
  858. EXITPROC(1, TEXT("WWW_RegisterURLEcho=%08X"), hddRet);
  859. return hddRet;
  860. }
  861. //
  862. // WWW_UnregisterURLEcho - unregister a DDE server
  863. //
  864. // Parameters:
  865. // qcsServer - the DDE server to stop getting notifications
  866. //
  867. // Returns:
  868. // fSuccess
  869. //
  870. HDDEDATA CIEDDEThread::WWW_UnregisterURLEcho(LPTSTR pszParams)
  871. {
  872. HDDEDATA hddRet = 0;
  873. BOOL fSuccess = FALSE;
  874. LPTSTR pszServer;
  875. ENTERPROC(1, TEXT("WWW_UnregisterURLEcho(pszParams=>%s<)"), pszParams);
  876. if (ParseQString(&pszParams, &pszServer) && pszServer[0])
  877. {
  878. if (g_pIEDDE->RemoveUrlEcho(pszServer))
  879. {
  880. fSuccess = TRUE;
  881. }
  882. else
  883. {
  884. TraceMsg(TF_WARNING, "IEDDE: UnregisterURLEcho could not find the server");
  885. }
  886. }
  887. else
  888. {
  889. TraceMsg(TF_WARNING, "IEDDE: UnregisterURLEcho could not parse parameters");
  890. }
  891. hddRet = CREATE_HDD(fSuccess);
  892. EXITPROC(1, TEXT("WWW_UnregisterURLEcho=%08X"), hddRet);
  893. return hddRet;
  894. }
  895. //
  896. // WWW_RegisterProtocol - register a server for handling a protocol
  897. //
  898. // Parameters:
  899. // qcsServer - the DDE server to handle URLs
  900. // qcsProtocol - the protocol to handle
  901. //
  902. // Returns:
  903. // fSuccess - this is the first server to register the protocol
  904. //
  905. HDDEDATA CIEDDEThread::WWW_RegisterProtocol(LPTSTR pszParams)
  906. {
  907. HDDEDATA hddRet = 0;
  908. BOOL fSuccess = FALSE;
  909. LPTSTR pszServer, pszProtocol;
  910. ENTERPROC(1, TEXT("WWW_RegisterProtocol(pszParams=>%s<)"), pszParams);
  911. if (ParseQString(&pszParams, &pszServer) && pszServer[0] &&
  912. ParseQString(&pszParams, &pszProtocol) && pszProtocol[0])
  913. {
  914. if (g_pIEDDE->AddProtocolHandler(pszServer, pszProtocol))
  915. {
  916. fSuccess = TRUE;
  917. }
  918. else
  919. {
  920. TraceMsg(TF_WARNING, "IEDDE: RegisterProtocol unable to register");
  921. }
  922. }
  923. else
  924. {
  925. TraceMsg(TF_WARNING, "IEDDE: RegisterProtocol could not parse parameters");
  926. }
  927. hddRet = CREATE_HDD(fSuccess);
  928. EXITPROC(1, TEXT("WWW_RegisterProtocol=%08X"), hddRet);
  929. return hddRet;
  930. }
  931. //
  932. // WWW_UnregisterProtocol - unregister a server handling a protocol
  933. //
  934. // Parameters:
  935. // qcsServer - the DDE server which is handling URLs
  936. // qcsProtocol - the protocol getting handled
  937. //
  938. // Returns:
  939. // fSuccess - this server was registered, but now isn't
  940. //
  941. HDDEDATA CIEDDEThread::WWW_UnregisterProtocol(LPTSTR pszParams)
  942. {
  943. HDDEDATA hddRet = 0;
  944. BOOL fSuccess = FALSE;
  945. LPTSTR pszServer, pszProtocol;
  946. ENTERPROC(1, TEXT("WWW_UnregisterProtocol(pszParams=>%s<)"), pszParams);
  947. if (ParseQString(&pszParams, &pszServer) && pszServer[0] &&
  948. ParseQString(&pszParams, &pszProtocol) && pszProtocol[0])
  949. {
  950. if (g_pIEDDE->RemoveProtocolHandler(pszServer, pszProtocol))
  951. {
  952. fSuccess = TRUE;
  953. }
  954. else
  955. {
  956. TraceMsg(TF_WARNING, "IEDDE: UnregisterProtocol unable to unregister");
  957. }
  958. }
  959. else
  960. {
  961. TraceMsg(TF_WARNING, "IEDDE: UnregisterProtocol could not parse parameters");
  962. }
  963. hddRet = CREATE_HDD(fSuccess);
  964. EXITPROC(1, TEXT("WWW_UnregisterProtocol=%08X"), hddRet);
  965. return hddRet;
  966. }
  967. //
  968. // WWW_ListWindows - Get a list of DDE supported browser window IDs
  969. //
  970. // Parameters:
  971. // none
  972. //
  973. // Returns:
  974. // pdwWindowID (terminated with 0)
  975. //
  976. HDDEDATA CIEDDEThread::WWW_ListWindows(LPTSTR pszParams)
  977. {
  978. HDDEDATA hddRet = 0;
  979. ENTERPROC(1, TEXT("WWW_ListWindows(pszParams=>%s<)"), pszParams);
  980. ENTER_IEDDE_CRIT;
  981. DWORD cbAlloc, *pdwWindowID;
  982. int cWindows = 0;
  983. HDSA hdsaWinitem = g_pIEDDE->GetHdsaWinitem();
  984. if (hdsaWinitem)
  985. {
  986. cWindows = DSA_GetItemCount(hdsaWinitem);
  987. }
  988. //
  989. // Note: we are following the Netscape spec (null terminated pdw) here,
  990. // whereas IE3 followed the Spyglass spec (pdw[0] = count of windows).
  991. //
  992. cbAlloc = (cWindows + 1) * SIZEOF(DWORD);
  993. pdwWindowID = (DWORD *)LocalAlloc(LPTR, cbAlloc);
  994. if (pdwWindowID)
  995. {
  996. DWORD *pdw;
  997. pdw = pdwWindowID;
  998. for (int i=0; i<cWindows; i++)
  999. {
  1000. WINITEM wi;
  1001. int iResult = DSA_GetItem(hdsaWinitem, i, &wi);
  1002. if (iResult != -1)
  1003. {
  1004. *pdw++ = wi.dwWindowID;
  1005. }
  1006. else
  1007. {
  1008. TraceMsg(TF_WARNING, "IEDDE: ListWindows could not get a DSA item");
  1009. }
  1010. }
  1011. hddRet = CreateReturnObject(pdwWindowID, cbAlloc);
  1012. }
  1013. else
  1014. {
  1015. TraceMsg(TF_WARNING, "IEDDE: ListWindows could not allocate a window list");
  1016. }
  1017. LEAVE_IEDDE_CRIT;
  1018. EXITPROC(1, TEXT("WWW_ListWindows=%08X"), hddRet);
  1019. return hddRet;
  1020. }
  1021. //
  1022. // MakeQuotedString - wrap a string in " marks, escaping internal "s as \"
  1023. //
  1024. BOOL CIEDDEThread::MakeQuotedString(LPCTSTR pszInput, LPTSTR pszOutput, int cchOutput)
  1025. {
  1026. BOOL fRet = FALSE;
  1027. ENTERPROC(2, TEXT("MakeQuotedString(pszInput=>%s<,pszOutput=%08X,cchOutput=%08X)"), pszInput, pszOutput, cchOutput);
  1028. if (cchOutput < 3)
  1029. {
  1030. TraceMsg(TF_WARNING, "IEDDE: MakeQuotedString has no room for minimal quoted string");
  1031. }
  1032. else if ((pszInput == NULL) || (*pszInput == TEXT('\0')))
  1033. {
  1034. StrCpyN(pszOutput, TEXT("\"\""), cchOutput);
  1035. fRet = TRUE;
  1036. }
  1037. else
  1038. {
  1039. //
  1040. // Copy first quote mark.
  1041. //
  1042. *pszOutput++ = TEXT('"');
  1043. cchOutput--;
  1044. //
  1045. // Copy pszInput, escaping quote marks and making
  1046. // sure to leave room for final quote and NULL.
  1047. //
  1048. while ((cchOutput > 2) && (*pszInput))
  1049. {
  1050. if (*pszInput == TEXT('"'))
  1051. {
  1052. *pszOutput++ = TEXT('\\');
  1053. cchOutput--;
  1054. }
  1055. *pszOutput++ = *pszInput++;
  1056. cchOutput--;
  1057. }
  1058. //
  1059. // Copy final quote and NULL if we're done and there is room.
  1060. //
  1061. if ((*pszInput == TEXT('\0')) && (cchOutput >= 2))
  1062. {
  1063. StrCpyN(pszOutput, TEXT("\""), cchOutput);
  1064. fRet = TRUE;
  1065. }
  1066. else
  1067. {
  1068. TraceMsg(TF_WARNING, "IEDDE: MakeQuotedString ran out of room in output buffer");
  1069. }
  1070. }
  1071. EXITPROC(2, TEXT("MakeQuotedString=%d"), fRet);
  1072. return fRet;
  1073. }
  1074. #undef CIEDDEThread
  1075. //
  1076. // There is one global CIEDDE object per process.
  1077. // It maintains the global information, such as
  1078. // the list of all browsers & what threads they are on,
  1079. // and the list of all apps who have registered an URL Echo.
  1080. //
  1081. // Its methods consist of these categories:
  1082. // the DDE callback function
  1083. // an internal handler for each exposed IEDDE_ function
  1084. // database (hdsa, hdpa) access and manipulation functions
  1085. //
  1086. // This object creates and destroys CIEDDEThread objects
  1087. // (at NewWindow and WindowDestroyed time) and also initializes /
  1088. // uninitializes DDE services on a per thread (not per hwnd!) basis.
  1089. //
  1090. //
  1091. // DdeCallback - DDE callback function for IEDDE.
  1092. //
  1093. #define DDETYPESTR(x) (x == XTYP_REQUEST ? TEXT("Request") : \
  1094. (x == XTYP_POKE ? TEXT("Poke") : \
  1095. (x == XTYP_EXECUTE ? TEXT("Execute") : \
  1096. (x == XTYP_CONNECT ? TEXT("Connect") : TEXT("Unknown")))))
  1097. HDDEDATA CIEDDE::DdeCallback(UINT dwType, UINT dwFmt, HCONV hconv, HSZ hsz1, HSZ hsz2, HDDEDATA hdd, DWORD dwData1, DWORD dwData2)
  1098. {
  1099. HDDEDATA hddRet = 0;
  1100. ENTERPROC(2, TEXT("DdeCallback(dwType=%08X(%s),dwFmt=%d,hconv=%d,hsz1=%08X,hsz2=%08X,hdd=%08X,dwData1=%08X,dwData2=%08X)"),
  1101. dwType, DDETYPESTR(dwType), dwFmt, hconv, hsz1, hsz2, hdd, dwData1, dwData2);
  1102. WINITEM wi;
  1103. switch (dwType)
  1104. {
  1105. case XTYP_REQUEST:
  1106. case XTYP_POKE:
  1107. if (g_pIEDDE->_GetWinitemFromThread(GetCurrentThreadId(), &wi))
  1108. {
  1109. hddRet = wi.pidt->OnRequestPoke(hsz1, hsz2);
  1110. }
  1111. else
  1112. {
  1113. TraceMsg(TF_WARNING, "IEDDE: DdeCallback unable to get thread info on request / poke");
  1114. }
  1115. break;
  1116. case XTYP_EXECUTE:
  1117. if (g_pIEDDE->_GetWinitemFromThread(GetCurrentThreadId(), &wi))
  1118. {
  1119. hddRet = wi.pidt->OnExecute(hsz1, hdd);
  1120. }
  1121. else
  1122. {
  1123. TraceMsg(TF_WARNING, "IEDDE: DdeCallback unable to get thread info on execute");
  1124. }
  1125. break;
  1126. case XTYP_CONNECT:
  1127. if (g_pIEDDE->_GetWinitemFromThread(GetCurrentThreadId(), &wi))
  1128. {
  1129. DDETHREADINFO dti;
  1130. wi.pidt->GetDdeThreadInfo(&dti);
  1131. hddRet = (HDDEDATA)(hsz2 == dti.hszService);
  1132. }
  1133. else
  1134. {
  1135. TraceMsg(TF_WARNING, "IEDDE: DdeCallback unable to get thread info on connect");
  1136. }
  1137. break;
  1138. case XTYP_ADVREQ:
  1139. case XTYP_ADVSTOP:
  1140. hddRet = DDE_FNOTPROCESSED;
  1141. break;
  1142. }
  1143. EXITPROC(2, TEXT("DdeCallback=%08X"), hddRet);
  1144. return hddRet;
  1145. }
  1146. //
  1147. // SendDDEMessageHsz - handle based wrapper for doing one DDE client transaction
  1148. //
  1149. HDDEDATA CIEDDE::_SendDDEMessageHsz(DWORD dwDDEInst, HSZ hszApp, HSZ hszTopic, HSZ hszMessage, UINT wType)
  1150. {
  1151. HDDEDATA hddRet = 0;
  1152. ENTERPROC(2, TEXT("_SendDDEMessageHsz(dwDDEInst=%08X,hszApp=%08X,hszTopic=%08X,hszMessage=%08X,wType=%d)"), dwDDEInst, hszApp, hszTopic, hszMessage, wType);
  1153. if (hszApp && hszTopic)
  1154. {
  1155. HCONV hconv;
  1156. hconv = DdeConnect(dwDDEInst, hszApp, hszTopic, NULL);
  1157. if (hconv)
  1158. {
  1159. hddRet = DdeClientTransaction(NULL, 0, hconv, hszMessage, CF_TEXT, wType, TEN_SECONDS, NULL);
  1160. DdeDisconnect(hconv);
  1161. }
  1162. else
  1163. {
  1164. TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageHsz could not connect to app");
  1165. }
  1166. }
  1167. else
  1168. {
  1169. TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageHsz is missing either App or Topic");
  1170. }
  1171. EXITPROC(2, TEXT("_SendDDEMessageHsz=%08X"), hddRet);
  1172. return hddRet;
  1173. }
  1174. //
  1175. // SendDDEMessageSz - string based wrapper for doing one DDE client transaction
  1176. //
  1177. HDDEDATA CIEDDE::_SendDDEMessageSz(DWORD dwDDEInst, LPCTSTR pszApp, LPCTSTR pszTopic, LPCTSTR pszMessage, UINT wType)
  1178. {
  1179. HDDEDATA hddRet = 0;
  1180. ENTERPROC(2, TEXT("_SendDDEMessageSz(dwDDEInst=%08X,pszApp=>%s<,pszTopic=>%s<,pszMessage=>%s<,wType=%d)"), dwDDEInst, pszApp, pszTopic, pszMessage, wType);
  1181. HSZ hszApp = DdeCreateStringHandle(dwDDEInst, pszApp, CP_WINNEUTRAL);
  1182. if (hszApp)
  1183. {
  1184. HSZ hszTopic = DdeCreateStringHandle(dwDDEInst, pszTopic, CP_WINNEUTRAL);
  1185. if (hszTopic)
  1186. {
  1187. HSZ hszMessage = DdeCreateStringHandle(dwDDEInst, pszMessage, CP_WINNEUTRAL);
  1188. if (hszMessage)
  1189. {
  1190. hddRet = _SendDDEMessageHsz(dwDDEInst, hszApp, hszTopic, hszMessage, wType);
  1191. DdeFreeStringHandle(dwDDEInst, hszMessage);
  1192. }
  1193. else
  1194. {
  1195. TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageSz could not convert message");
  1196. }
  1197. DdeFreeStringHandle(dwDDEInst, hszTopic);
  1198. }
  1199. else
  1200. {
  1201. TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageSz could not convert topic");
  1202. }
  1203. DdeFreeStringHandle(dwDDEInst, hszApp);
  1204. }
  1205. else
  1206. {
  1207. TraceMsg(TF_WARNING, "IEDDE: _SendDDEMessageSz could not convert app");
  1208. }
  1209. EXITPROC(2, TEXT("_SendDDEMessageSz=%08X"), hddRet);
  1210. return hddRet;
  1211. }
  1212. //
  1213. // Initialize - called when ready to start IEDDE server
  1214. //
  1215. BOOL CIEDDE::_Initialize(void)
  1216. {
  1217. BOOL fSuccess = TRUE;
  1218. ENTERPROC(2, TEXT("_Initialize()"));
  1219. ASSERT(_fCSInitialized == FALSE);
  1220. InitializeCriticalSection(&_csIEDDE);
  1221. _fCSInitialized = TRUE;
  1222. EXITPROC(2, TEXT("_Initialize=%d"), fSuccess);
  1223. return fSuccess;
  1224. }
  1225. //
  1226. // _DestroyWinitem - DSA callback to partially free the contents of a WINITEM*
  1227. // In practice this should never get called, the hdsaWinItem list should be
  1228. // empty at uninit time.
  1229. //
  1230. int CIEDDE::_DestroyWinitem(LPVOID p1, LPVOID p2)
  1231. {
  1232. WINITEM *pwi = (WINITEM *)p1;
  1233. ASSERT(IS_VALID_READ_PTR(pwi, WINITEM));
  1234. ASSERT(IS_VALID_READ_PTR(pwi->pidt, CIEDDEThread));
  1235. //
  1236. // It would be good to unregister the DDE server at this point,
  1237. // but we'd need to be on its thread to do it.
  1238. //
  1239. delete pwi->pidt;
  1240. return 1;
  1241. }
  1242. //
  1243. // _DestroyProtocol - DSA callback to free the contents of a PROTOCOLREG*
  1244. //
  1245. int CIEDDE::_DestroyProtocol(LPVOID p1, LPVOID p2)
  1246. {
  1247. PROTOCOLREG *pr = (PROTOCOLREG *)p1;
  1248. ASSERT(IS_VALID_READ_PTR(pr, PROTOCOLREG));
  1249. LocalFree(pr->pszProtocol);
  1250. pr->pszProtocol = NULL;
  1251. LocalFree(pr->pszServer);
  1252. pr->pszServer = NULL;
  1253. return 1;
  1254. }
  1255. //
  1256. // _DestroyUrlEcho - DPA callback to free allocated memory
  1257. //
  1258. int CIEDDE::_DestroyUrlEcho(LPVOID p1, LPVOID p2)
  1259. {
  1260. ASSERT(IS_VALID_STRING_PTR((LPTSTR)p1, -1));
  1261. LocalFree(p1);
  1262. p1 = NULL;
  1263. return 1;
  1264. }
  1265. //
  1266. // Uninitialize - called when ready to stop IEDDE server
  1267. //
  1268. void CIEDDE::_Uninitialize(void)
  1269. {
  1270. ENTERPROC(2, TEXT("_Uninitialize()"));
  1271. _fAutomationReady = FALSE;
  1272. if (_hdsaWinitem)
  1273. {
  1274. if (DSA_GetItemCount(_hdsaWinitem))
  1275. {
  1276. //ASSERT(DSA_GetItemCount(_hdsaWinitem)==0);
  1277. TraceMsg(TF_ERROR, "IEDDE: Browser windows still open on uninitialize");
  1278. }
  1279. DSA_DestroyCallback(_hdsaWinitem, _DestroyWinitem, 0);
  1280. _hdsaWinitem = NULL;
  1281. }
  1282. if (_hdsaProtocolHandler)
  1283. {
  1284. DSA_DestroyCallback(_hdsaProtocolHandler, _DestroyProtocol, 0);
  1285. _hdsaProtocolHandler = NULL;
  1286. }
  1287. if (_hdpaUrlEcho)
  1288. {
  1289. DPA_DestroyCallback(_hdpaUrlEcho, _DestroyUrlEcho, 0);
  1290. _hdpaUrlEcho = NULL;
  1291. }
  1292. if (_fCSInitialized)
  1293. {
  1294. DeleteCriticalSection(&_csIEDDE);
  1295. }
  1296. EXITPROC(2, TEXT("_Uninitialize!"));
  1297. }
  1298. void CIEDDE::SetDelayedExecute(LPCTSTR pszTopic, LPCTSTR pszParams)
  1299. {
  1300. _dwThreadID = GetCurrentThreadId();
  1301. Str_SetPtr(&_pszTopic, pszTopic);
  1302. Str_SetPtr(&_pszParams, pszParams);
  1303. }
  1304. void CIEDDE::RunDelayedExecute()
  1305. {
  1306. if (_pszTopic && _pszParams)
  1307. {
  1308. WINITEM wi;
  1309. if (_GetWinitemFromThread(_dwThreadID, &wi) && wi.pidt)
  1310. {
  1311. HDDEDATA h = wi.pidt->CallTopic(XTYP_EXECUTE, _pszTopic, _pszParams);
  1312. DdeFreeDataHandle(h);
  1313. }
  1314. }
  1315. Str_SetPtr(&_pszTopic, NULL);
  1316. Str_SetPtr(&_pszParams, NULL);
  1317. }
  1318. //
  1319. // _AutomationStarted - called when automation support can be called
  1320. //
  1321. void CIEDDE::_AutomationStarted(void)
  1322. {
  1323. ENTERPROC(1, TEXT("_AutomationStarted()"));
  1324. if (!_fAutomationReady && _pszTopic && _pszParams)
  1325. {
  1326. WINITEM wi;
  1327. if (_GetWinitemFromThread(_dwThreadID, &wi) && wi.pidt)
  1328. {
  1329. PostMessage(wi.hwnd, WMC_DELAYEDDDEEXEC, 0, 0);
  1330. }
  1331. }
  1332. _fAutomationReady = TRUE;
  1333. EXITPROC(1, TEXT("_AutomationStarted!"));
  1334. }
  1335. //
  1336. // _BeforeNavigate - called before a navigation occurs.
  1337. //
  1338. HRESULT CIEDDE::_BeforeNavigate(LPCTSTR pszURL, BOOL *pfProcessed)
  1339. {
  1340. ENTERPROC(1, TEXT("_BeforeNavigate(pszURL=>%s<,pfProcessed=%08X)"), pszURL, pfProcessed);
  1341. SHSTR shstrMsg;
  1342. HRESULT hr = S_OK;
  1343. int cProtocols = 0;
  1344. ENTER_IEDDE_CRIT;
  1345. if (_hdsaProtocolHandler)
  1346. {
  1347. cProtocols = DSA_GetItemCount(_hdsaProtocolHandler);
  1348. }
  1349. LEAVE_IEDDE_CRIT;
  1350. if (cProtocols)
  1351. {
  1352. DDETHREADINFO dti;
  1353. if (_GetDtiFromThread(GetCurrentThreadId(), &dti))
  1354. {
  1355. PARSEDURL pu;
  1356. pu.cbSize = SIZEOF(pu);
  1357. if (SUCCEEDED(ParseURL(pszURL, &pu)))
  1358. {
  1359. int i;
  1360. for (i=0; i<cProtocols; i++)
  1361. {
  1362. PROTOCOLREG pr;
  1363. ENTER_IEDDE_CRIT;
  1364. int iResult = DSA_GetItem(_hdsaProtocolHandler, i, &pr);
  1365. LEAVE_IEDDE_CRIT;
  1366. if (iResult != -1)
  1367. {
  1368. //
  1369. // Check to see if the protocol to navigate
  1370. // matches one of our registered protocols.
  1371. // We do a case insensitive compare. Note
  1372. // that:
  1373. //
  1374. // (1) ParseURL does not null terminate the
  1375. // pu.pszProtocol (its length is stored
  1376. // in pu.cchProtocol).
  1377. //
  1378. // (2) pu.pszProtocol is a LPCTSTR so we
  1379. // can't modify the pszProtocol ourselves.
  1380. //
  1381. // (3) There is no win32 lstrncmpi() API.
  1382. //
  1383. // Therefore in order to do a case insensitive
  1384. // compare we must copy the pu.pszProtocol into
  1385. // a writable buffer at some point.
  1386. //
  1387. if (lstrlen(pr.pszProtocol) == (int)pu.cchProtocol)
  1388. {
  1389. shstrMsg.SetStr(pu.pszProtocol, pu.cchProtocol);
  1390. if (StrCmpI(pr.pszProtocol, shstrMsg) == 0)
  1391. {
  1392. shstrMsg.SetStr(TEXT("\""));
  1393. shstrMsg.Append(pszURL);
  1394. shstrMsg.Append(TEXT("\",,-1,0,,,,"));
  1395. if (_SendDDEMessageSz(dti.dwDDEInst, pr.pszServer, c_szWWWOpenURL, shstrMsg, XTYP_REQUEST))
  1396. {
  1397. if (pfProcessed)
  1398. {
  1399. *pfProcessed = TRUE;
  1400. }
  1401. }
  1402. else
  1403. {
  1404. TraceMsg(TF_WARNING, "IEDDE: _BeforeNavigate could not DDE to protocol handler");
  1405. }
  1406. break;
  1407. }
  1408. }
  1409. }
  1410. else
  1411. {
  1412. TraceMsg(TF_WARNING, "IEDDE: _BeforeNavigate could not get item from DSA");
  1413. }
  1414. }
  1415. }
  1416. else
  1417. {
  1418. TraceMsg(TF_WARNING, "IEDDE: _BeforeNavigate could not parse URL");
  1419. }
  1420. }
  1421. else
  1422. {
  1423. TraceMsg(TF_WARNING, "IEDDE: _BeforeNavigate unable to get thread info, can't use DDE");
  1424. }
  1425. }
  1426. EXITPROC(1, TEXT("_BeforeNavigate=%08X"), hr);
  1427. return hr;
  1428. }
  1429. //
  1430. // _AfterNavigate - called after a navigation occurs
  1431. //
  1432. HRESULT CIEDDE::_AfterNavigate(LPCTSTR pszURL, HWND hwnd)
  1433. {
  1434. ENTERPROC(1, TEXT("_AfterNavigate(pszURL=>%s<,hwnd=%08X)"), pszURL, hwnd);
  1435. int cURLHooks = 0;
  1436. SHSTR shstrMsg;
  1437. HRESULT hr = S_OK;
  1438. ENTER_IEDDE_CRIT;
  1439. if (_hdpaUrlEcho)
  1440. {
  1441. cURLHooks = DPA_GetPtrCount(_hdpaUrlEcho);
  1442. }
  1443. LEAVE_IEDDE_CRIT;
  1444. if (cURLHooks)
  1445. {
  1446. SHSTR shstrMime;
  1447. // (mattsq 1-97)
  1448. // this is a temporary lie - it should be fixed to use the real mimetype
  1449. // with something like:
  1450. // GetMimeTypeFromUrl(pszURL, shstrMime);
  1451. // talk to URLMON people
  1452. shstrMime.SetStr(TEXT("text/html"));
  1453. DDETHREADINFO dti={0};
  1454. WINITEM wi;
  1455. DWORD dwWindowID;
  1456. if (GetWinitemFromHwnd(hwnd, &wi))
  1457. {
  1458. dwWindowID = wi.dwWindowID;
  1459. wi.pidt->GetDdeThreadInfo(&dti);
  1460. }
  1461. else
  1462. {
  1463. TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to find browser window ID, using -1");
  1464. dwWindowID = (DWORD)-1;
  1465. WINITEM wiThread;
  1466. if (_GetWinitemFromThread(GetCurrentThreadId(), &wiThread))
  1467. {
  1468. ASSERT(wiThread.pidt);
  1469. wiThread.pidt->GetDdeThreadInfo(&dti);
  1470. }
  1471. else
  1472. {
  1473. TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to find DDE thread info");
  1474. }
  1475. }
  1476. if (dti.dwDDEInst)
  1477. {
  1478. HSZ hszTopic = DdeCreateStringHandle(dti.dwDDEInst, c_szWWWUrlEcho, CP_WINNEUTRAL);
  1479. if (hszTopic)
  1480. {
  1481. TCHAR szFinish[16];
  1482. shstrMsg.SetStr(TEXT("\"")); // Quote
  1483. shstrMsg.Append(pszURL); // URL
  1484. shstrMsg.Append(TEXT("\",\"")); // Quote Comma Quote
  1485. shstrMsg.Append(shstrMime); // Mime
  1486. wnsprintf(szFinish, ARRAYSIZE(szFinish), TEXT("\",%d"), dwWindowID); //
  1487. shstrMsg.Append(szFinish); // Quote Comma dwWindowID NULL
  1488. HSZ hszMsg = DdeCreateStringHandle(dti.dwDDEInst, shstrMsg, CP_WINNEUTRAL);
  1489. if (hszMsg)
  1490. {
  1491. //
  1492. // Enumerate in reverse order because calling a hook may destroy it.
  1493. //
  1494. for (int i=cURLHooks-1; i>=0; --i)
  1495. {
  1496. ENTER_IEDDE_CRIT;
  1497. LPTSTR pszService = (LPTSTR)DPA_GetPtr(_hdpaUrlEcho, i);
  1498. LEAVE_IEDDE_CRIT;
  1499. if (pszService != NULL)
  1500. {
  1501. HSZ hszService = DdeCreateStringHandle(dti.dwDDEInst, pszService, CP_WINNEUTRAL);
  1502. if (hszService)
  1503. {
  1504. if (_SendDDEMessageHsz(dti.dwDDEInst, hszService, hszTopic, hszMsg, XTYP_POKE) == 0)
  1505. {
  1506. TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate could not DDE to URLHook handler");
  1507. }
  1508. DdeFreeStringHandle(dti.dwDDEInst, hszService);
  1509. }
  1510. else
  1511. {
  1512. TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to create hszService");
  1513. }
  1514. }
  1515. else
  1516. {
  1517. TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to enumerate an URL hook");
  1518. }
  1519. }
  1520. DdeFreeStringHandle(dti.dwDDEInst, hszMsg);
  1521. }
  1522. else
  1523. {
  1524. TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to create hszMsg");
  1525. }
  1526. DdeFreeStringHandle(dti.dwDDEInst, hszTopic);
  1527. }
  1528. else
  1529. {
  1530. TraceMsg(TF_WARNING, "IEDDE: _AfterNavigate unable to create hszTopic");
  1531. }
  1532. }
  1533. }
  1534. EXITPROC(1, TEXT("_AfterNavigate=%08X"), hr);
  1535. return hr;
  1536. }
  1537. //
  1538. // GetWinitemFromHwnd - return the winitem associated with an hwnd
  1539. //
  1540. BOOL CIEDDE::GetWinitemFromHwnd(HWND hwnd, WINITEM *pwi)
  1541. {
  1542. BOOL fSuccess = FALSE;
  1543. ENTERPROC(2, TEXT("GetWinitemFromHwnd(hwnd=%08X,pwi=%08X)"), hwnd, pwi);
  1544. ENTER_IEDDE_CRIT;
  1545. if (_hdsaWinitem)
  1546. {
  1547. for (int i=0; i<DSA_GetItemCount(_hdsaWinitem); i++)
  1548. {
  1549. WINITEM wi;
  1550. if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1)
  1551. {
  1552. if (wi.hwnd == hwnd)
  1553. {
  1554. *pwi = wi;
  1555. fSuccess = TRUE;
  1556. break;
  1557. }
  1558. }
  1559. }
  1560. }
  1561. LEAVE_IEDDE_CRIT;
  1562. EXITPROC(2, TEXT("GetWinitemFromHwnd=%d"), fSuccess);
  1563. return fSuccess;
  1564. }
  1565. //
  1566. // GetWinitemFromWindowID - return the winitem associated with a window ID
  1567. //
  1568. BOOL CIEDDE::GetWinitemFromWindowID(DWORD dwWindowID, WINITEM *pwi)
  1569. {
  1570. BOOL fSuccess = FALSE;
  1571. ENTERPROC(3, TEXT("GetWinitemFromWindowID(dwWindowID=%08X,pwi=%08X)"), dwWindowID, pwi);
  1572. ENTER_IEDDE_CRIT;
  1573. if (_hdsaWinitem)
  1574. {
  1575. for (int i=0; i<DSA_GetItemCount(_hdsaWinitem); i++)
  1576. {
  1577. WINITEM wi;
  1578. if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1)
  1579. {
  1580. if (wi.dwWindowID == dwWindowID)
  1581. {
  1582. *pwi = wi;
  1583. fSuccess = TRUE;
  1584. break;
  1585. }
  1586. }
  1587. }
  1588. }
  1589. LEAVE_IEDDE_CRIT;
  1590. EXITPROC(2, TEXT("GetWinitemFromWindowID=%d"), fSuccess);
  1591. return fSuccess;
  1592. }
  1593. //
  1594. // _GetWinitemFromThread - return the first winitem associated with a thread
  1595. //
  1596. BOOL CIEDDE::_GetWinitemFromThread(DWORD dwThreadID, WINITEM *pwi)
  1597. {
  1598. BOOL fSuccess = FALSE;
  1599. ENTERPROC(2, TEXT("_GetWinitemFromThread(dwThreadID=%08X,pwi=%08X)"), dwThreadID, pwi);
  1600. ENTER_IEDDE_CRIT;
  1601. if (_hdsaWinitem)
  1602. {
  1603. for (int i=0; i<DSA_GetItemCount(_hdsaWinitem); i++)
  1604. {
  1605. WINITEM wi;
  1606. if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1)
  1607. {
  1608. if (wi.dwThreadID == dwThreadID)
  1609. {
  1610. *pwi = wi;
  1611. fSuccess = TRUE;
  1612. break;
  1613. }
  1614. }
  1615. }
  1616. }
  1617. LEAVE_IEDDE_CRIT;
  1618. EXITPROC(2, TEXT("_GetWinitemFromThread=%d"), fSuccess);
  1619. return fSuccess;
  1620. }
  1621. //
  1622. // _GetDtiFromThread - return the threadinfo associated with a thread
  1623. //
  1624. BOOL CIEDDE::_GetDtiFromThread(DWORD dwThreadID, DDETHREADINFO *pdti)
  1625. {
  1626. BOOL fSuccess = FALSE;
  1627. ENTERPROC(2, TEXT("_GetDtiFromThread(dwThreadID=%08X,pdti=%08X)"), dwThreadID, pdti);
  1628. ENTER_IEDDE_CRIT;
  1629. WINITEM wi;
  1630. if (_GetWinitemFromThread(dwThreadID, &wi))
  1631. {
  1632. wi.pidt->GetDdeThreadInfo(pdti);
  1633. fSuccess = TRUE;
  1634. }
  1635. else
  1636. {
  1637. TraceMsg(TF_WARNING, "IEDDE: _GetDtiFromThread unable to find winitem");
  1638. }
  1639. LEAVE_IEDDE_CRIT;
  1640. EXITPROC(2, TEXT("_GetDtiFromThread=%d"), fSuccess);
  1641. return fSuccess;
  1642. }
  1643. //
  1644. // _CreateDdeThreadInfo - Initialize DDE services and names for this thread
  1645. //
  1646. BOOL CIEDDE::_CreateDdeThreadInfo(DDETHREADINFO *pdti)
  1647. {
  1648. BOOL fSuccess = FALSE;
  1649. ENTERPROC(2, TEXT("_CreateDdeThreadInfo(pdti=%08X)"), pdti);
  1650. UINT uiDDE;
  1651. DDETHREADINFO dti={0};
  1652. //
  1653. // Initialize DDEML, register our service.
  1654. //
  1655. uiDDE = DdeInitialize(&dti.dwDDEInst, (PFNCALLBACK)DdeCallback,
  1656. APPCLASS_STANDARD | CBF_FAIL_ADVISES |
  1657. CBF_SKIP_REGISTRATIONS | CBF_SKIP_UNREGISTRATIONS, 0);
  1658. if (uiDDE == DMLERR_NO_ERROR)
  1659. {
  1660. dti.hszReturn = DdeCreateStringHandle(dti.dwDDEInst, c_szReturn, CP_WINNEUTRAL);
  1661. if (dti.hszReturn)
  1662. {
  1663. dti.hszService = DdeCreateStringHandle(dti.dwDDEInst, c_szIExplore, CP_WINNEUTRAL);
  1664. if (dti.hszService)
  1665. {
  1666. *pdti = dti;
  1667. fSuccess = TRUE;
  1668. }
  1669. else
  1670. {
  1671. TraceMsg(TF_WARNING, "IEDDE: _CreateDdeThreadInfo unable to convert service");
  1672. }
  1673. if (!fSuccess)
  1674. {
  1675. DdeFreeStringHandle(dti.dwDDEInst, dti.hszReturn);
  1676. }
  1677. }
  1678. else
  1679. {
  1680. TraceMsg(TF_WARNING, "IEDDE: _CreateDdeThreadInfo unable to convert return");
  1681. }
  1682. if (!fSuccess)
  1683. {
  1684. DdeUninitialize(dti.dwDDEInst);
  1685. }
  1686. }
  1687. else
  1688. {
  1689. TraceMsg(TF_WARNING, "IEDDE: _CreateDdeThreadInfo unable to init DDE");
  1690. }
  1691. EXITPROC(2, TEXT("_CreateDdeThreadInfo=%d"), fSuccess);
  1692. return fSuccess;
  1693. }
  1694. //
  1695. // _DestroyDdeThreadInfo - Free up any resources in a dti structure.
  1696. //
  1697. void CIEDDE::_DestroyDdeThreadInfo(DDETHREADINFO *pdti)
  1698. {
  1699. ENTERPROC(2, TEXT("_DestroyDdeThreadInfo(pdti=%08X)"), pdti);
  1700. if (pdti->hddNameService)
  1701. {
  1702. ASSERT(pdti->hszService);
  1703. DdeNameService(pdti->dwDDEInst, pdti->hszService, 0, DNS_UNREGISTER);
  1704. pdti->hddNameService = 0;
  1705. }
  1706. if (pdti->hszService)
  1707. {
  1708. DdeFreeStringHandle(pdti->dwDDEInst, pdti->hszService);
  1709. pdti->hszService = 0;
  1710. }
  1711. if (pdti->hszReturn)
  1712. {
  1713. DdeFreeStringHandle(pdti->dwDDEInst, pdti->hszReturn);
  1714. pdti->hszReturn = 0;
  1715. }
  1716. if (pdti->dwDDEInst)
  1717. {
  1718. DdeUninitialize(pdti->dwDDEInst);
  1719. pdti->dwDDEInst = 0;
  1720. }
  1721. EXITPROC(2, TEXT("_DestroyDdeThreadInfo!"));
  1722. return;
  1723. }
  1724. //
  1725. // _AddWinitem - adds a winitem to _hdsaWinitem
  1726. //
  1727. BOOL CIEDDE::_AddWinitem(WINITEM *pwi)
  1728. {
  1729. BOOL fSuccess = FALSE;
  1730. ENTERPROC(2, TEXT("_AddWinitem(pwi=%08X)"), pwi);
  1731. ENTER_IEDDE_CRIT;
  1732. if (!_hdsaWinitem)
  1733. {
  1734. _hdsaWinitem = DSA_Create(SIZEOF(WINITEM), DXA_GROWTH_AMOUNT);
  1735. }
  1736. if (_hdsaWinitem)
  1737. {
  1738. if (DSA_AppendItem(_hdsaWinitem, pwi) != -1)
  1739. {
  1740. fSuccess = TRUE;
  1741. }
  1742. else
  1743. {
  1744. TraceMsg(TF_WARNING, "IEDDE: _AddWinitem could not append an item");
  1745. }
  1746. }
  1747. else
  1748. {
  1749. TraceMsg(TF_WARNING, "IEDDE: _AddWinitem could not create hdsa");
  1750. }
  1751. LEAVE_IEDDE_CRIT;
  1752. EXITPROC(2, TEXT("_AddWinitem=%d"), fSuccess);
  1753. return fSuccess;
  1754. }
  1755. //
  1756. // _UpdateWinitem - updates a winitem based on the dwWindowID.
  1757. //
  1758. BOOL CIEDDE::_UpdateWinitem(WINITEM *pwi)
  1759. {
  1760. BOOL fSuccess = FALSE;
  1761. ENTERPROC(2, TEXT("_UpdateWinitem(pwi=%08X)"), pwi);
  1762. ENTER_IEDDE_CRIT;
  1763. if (_hdsaWinitem)
  1764. {
  1765. int cItems = DSA_GetItemCount(_hdsaWinitem);
  1766. for (int i=0; i<cItems; i++)
  1767. {
  1768. WINITEM wi;
  1769. if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1)
  1770. {
  1771. if (wi.dwWindowID == pwi->dwWindowID)
  1772. {
  1773. if (DSA_SetItem(_hdsaWinitem, i, pwi))
  1774. {
  1775. fSuccess = TRUE;
  1776. }
  1777. else
  1778. {
  1779. TraceMsg(TF_WARNING, "IEDDE: _UpdateWinitem could not update an item");
  1780. }
  1781. break;
  1782. }
  1783. }
  1784. else
  1785. {
  1786. TraceMsg(TF_WARNING, "IEDDE: _UpdateWinitem could not get an item");
  1787. }
  1788. }
  1789. }
  1790. LEAVE_IEDDE_CRIT;
  1791. EXITPROC(2, TEXT("_UpdateWinitem=%d"), fSuccess);
  1792. return fSuccess;
  1793. }
  1794. //
  1795. // AddUrlEcho - adds an UrlEcho entry to the dpa
  1796. //
  1797. BOOL CIEDDE::AddUrlEcho(LPCTSTR pszUrlEcho)
  1798. {
  1799. BOOL fSuccess = FALSE;
  1800. ENTERPROC(2, TEXT("AddUrlEcho(pszUrlEcho=>%s<)"), pszUrlEcho);
  1801. ENTER_IEDDE_CRIT;
  1802. if (!_hdpaUrlEcho)
  1803. {
  1804. _hdpaUrlEcho = DPA_Create(DXA_GROWTH_AMOUNT);
  1805. }
  1806. if (_hdpaUrlEcho)
  1807. {
  1808. if (DPA_AppendPtr(_hdpaUrlEcho, (LPVOID)pszUrlEcho) != -1)
  1809. {
  1810. fSuccess = TRUE;
  1811. }
  1812. else
  1813. {
  1814. TraceMsg(TF_WARNING, "IEDDE: AddUrlEcho unable to append a ptr");
  1815. }
  1816. }
  1817. else
  1818. {
  1819. TraceMsg(TF_WARNING, "IEDDE: AddUrlEcho unable to create a dpa");
  1820. }
  1821. LEAVE_IEDDE_CRIT;
  1822. EXITPROC(2, TEXT("AddUrlEcho=%d"), fSuccess);
  1823. return fSuccess;
  1824. }
  1825. //
  1826. // RemoveUrlEcho - remove an UrlEcho entry from the dpa
  1827. //
  1828. BOOL CIEDDE::RemoveUrlEcho(LPCTSTR pszUrlEcho)
  1829. {
  1830. BOOL fSuccess = FALSE;
  1831. ENTERPROC(2, TEXT("RemoveUrlEcho(pszUrlEcho=>%s<)"), pszUrlEcho);
  1832. ENTER_IEDDE_CRIT;
  1833. if (_hdpaUrlEcho)
  1834. {
  1835. for (int i=0; i<DPA_GetPtrCount(_hdpaUrlEcho); i++)
  1836. {
  1837. LPTSTR pszList = (LPTSTR)DPA_GetPtr(_hdpaUrlEcho, i);
  1838. if (pszList)
  1839. {
  1840. if (StrCmpI(pszList, pszUrlEcho) == 0)
  1841. {
  1842. DPA_DeletePtr(_hdpaUrlEcho, i);
  1843. LocalFree((HANDLE)pszList);
  1844. pszList = NULL;
  1845. fSuccess = TRUE;
  1846. break;
  1847. }
  1848. }
  1849. else
  1850. {
  1851. TraceMsg(TF_ALWAYS, "IEDDE: RemoveUrlEcho unable to get dpa ptr");
  1852. }
  1853. }
  1854. if (!fSuccess)
  1855. {
  1856. TraceMsg(TF_WARNING, "IEDDE: RemoveUrlEcho unable to find server");
  1857. }
  1858. }
  1859. else
  1860. {
  1861. TraceMsg(TF_WARNING, "IEDDE: RemoveUrlEcho unable to find dpa");
  1862. }
  1863. LEAVE_IEDDE_CRIT;
  1864. EXITPROC(2, TEXT("RemoveUrlEcho=%d"), fSuccess);
  1865. return fSuccess;
  1866. }
  1867. //
  1868. // AddProtocolHandler - add a PROTOCOLREG entry to the dsa
  1869. //
  1870. BOOL CIEDDE::AddProtocolHandler(LPCTSTR pszServer, LPCTSTR pszProtocol)
  1871. {
  1872. BOOL fSuccess = FALSE;
  1873. ENTERPROC(2, TEXT("AddProtocolHandler(pszServer=>%s<,pszProtocol=>%s<)"), pszServer, pszProtocol);
  1874. ENTER_IEDDE_CRIT;
  1875. PROTOCOLREG pr;
  1876. //
  1877. // First, see if anybody else grabbed the protocol first.
  1878. //
  1879. BOOL fFoundHandler = FALSE;
  1880. if (_hdsaProtocolHandler)
  1881. {
  1882. for (int i=0; i<DSA_GetItemCount(_hdsaProtocolHandler); i++)
  1883. {
  1884. if (DSA_GetItem(_hdsaProtocolHandler, i, &pr) != -1)
  1885. {
  1886. if (StrCmpI(pr.pszProtocol, pszProtocol) == 0)
  1887. {
  1888. TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler already has a handler");
  1889. fFoundHandler = TRUE;
  1890. break;
  1891. }
  1892. }
  1893. else
  1894. {
  1895. TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to get an item");
  1896. }
  1897. }
  1898. }
  1899. if (!fFoundHandler)
  1900. {
  1901. if (!_hdsaProtocolHandler)
  1902. {
  1903. _hdsaProtocolHandler = DSA_Create(SIZEOF(PROTOCOLREG), DXA_GROWTH_AMOUNT);
  1904. }
  1905. if (_hdsaProtocolHandler)
  1906. {
  1907. pr.pszServer = StrDup(pszServer);
  1908. if (pr.pszServer)
  1909. {
  1910. pr.pszProtocol = StrDup(pszProtocol);
  1911. if (pr.pszProtocol)
  1912. {
  1913. if (DSA_AppendItem(_hdsaProtocolHandler, &pr) != -1)
  1914. {
  1915. fSuccess = TRUE;
  1916. }
  1917. else
  1918. {
  1919. TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to append to dsa");
  1920. }
  1921. if (!fSuccess)
  1922. {
  1923. LocalFree((HANDLE)pr.pszProtocol);
  1924. pr.pszProtocol = NULL;
  1925. }
  1926. }
  1927. else
  1928. {
  1929. TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to dup protocol");
  1930. }
  1931. if (!fSuccess)
  1932. {
  1933. LocalFree((HANDLE)pr.pszServer);
  1934. pr.pszServer = NULL;
  1935. }
  1936. }
  1937. else
  1938. {
  1939. TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to dup server");
  1940. }
  1941. }
  1942. else
  1943. {
  1944. TraceMsg(TF_WARNING, "IEDDE: AddProtocolHandler unable to create dsa");
  1945. }
  1946. }
  1947. LEAVE_IEDDE_CRIT;
  1948. EXITPROC(2, TEXT("AddProtocolHandler=%d"), fSuccess);
  1949. return fSuccess;
  1950. }
  1951. //
  1952. // RemoveProtocolHandler - removes a PROTOCOLREG item from the dsa
  1953. //
  1954. BOOL CIEDDE::RemoveProtocolHandler(LPCTSTR pszServer, LPCTSTR pszProtocol)
  1955. {
  1956. BOOL fSuccess = FALSE;
  1957. ENTERPROC(2, TEXT("RemoveProtocolHandler(pszServer=>%s<,pszProtocol=>%s<)"), pszServer, pszProtocol);
  1958. ENTER_IEDDE_CRIT;
  1959. if (_hdsaProtocolHandler)
  1960. {
  1961. for (int i=0; i<DSA_GetItemCount(_hdsaProtocolHandler); i++)
  1962. {
  1963. PROTOCOLREG pr;
  1964. if (DSA_GetItem(_hdsaProtocolHandler, i, &pr) != -1)
  1965. {
  1966. if (StrCmpI(pr.pszProtocol, pszProtocol) == 0)
  1967. {
  1968. if (StrCmpI(pr.pszServer, pszServer) == 0)
  1969. {
  1970. if (DSA_DeleteItem(_hdsaProtocolHandler, i) != -1)
  1971. {
  1972. LocalFree((HANDLE)pr.pszServer);
  1973. pr.pszServer = NULL;
  1974. LocalFree((HANDLE)pr.pszProtocol);
  1975. pr.pszProtocol = NULL;
  1976. fSuccess = TRUE;
  1977. }
  1978. else
  1979. {
  1980. TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler unable to remove item");
  1981. }
  1982. }
  1983. else
  1984. {
  1985. TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler says server didn't match");
  1986. }
  1987. break;
  1988. }
  1989. }
  1990. else
  1991. {
  1992. TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler unable to get item");
  1993. }
  1994. }
  1995. if (!fSuccess)
  1996. {
  1997. TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler unable to complete mission");
  1998. }
  1999. }
  2000. else
  2001. {
  2002. TraceMsg(TF_WARNING, "IEDDE: RemoveProtocolHandler can't find the dsa");
  2003. }
  2004. LEAVE_IEDDE_CRIT;
  2005. EXITPROC(2, TEXT("RemoveProtocolHandler=%d"), fSuccess);
  2006. return fSuccess;
  2007. }
  2008. //
  2009. // _DeleteWinitemByHwnd - removes a winitem from _hdsaWinitem
  2010. //
  2011. BOOL CIEDDE::_DeleteWinitemByHwnd(HWND hwnd, WINITEM *pwi)
  2012. {
  2013. BOOL fSuccess = FALSE;
  2014. ENTERPROC(2, TEXT("_DeleteWinitemByHwnd(hwnd=%08X,pwi=%08X)"), hwnd, pwi);
  2015. ENTER_IEDDE_CRIT;
  2016. if (_hdsaWinitem)
  2017. {
  2018. for (int i=0; i<DSA_GetItemCount(_hdsaWinitem); i++)
  2019. {
  2020. WINITEM wi;
  2021. if (DSA_GetItem(_hdsaWinitem, i, &wi) != -1)
  2022. {
  2023. if (wi.hwnd == hwnd)
  2024. {
  2025. if (DSA_DeleteItem(_hdsaWinitem, i) != -1)
  2026. {
  2027. *pwi = wi;
  2028. fSuccess = TRUE;
  2029. }
  2030. else
  2031. {
  2032. TraceMsg(TF_WARNING, "IEDDE: _DeleteWinitemByHwnd could note delete an item");
  2033. }
  2034. break;
  2035. }
  2036. }
  2037. else
  2038. {
  2039. TraceMsg(TF_WARNING, "IEDDE: _DeleteWinitemByHwnd could note get an item");
  2040. }
  2041. }
  2042. }
  2043. else
  2044. {
  2045. TraceMsg(TF_WARNING, "IEDDE: _DeleteWinitemByHwnd has no _hdsaWinitem");
  2046. }
  2047. LEAVE_IEDDE_CRIT;
  2048. EXITPROC(2, TEXT("_DeleteWinitemByHwnd=%d"), fSuccess);
  2049. return fSuccess;
  2050. }
  2051. //
  2052. // _NewWindow - Add a browser window to the internal list
  2053. //
  2054. BOOL CIEDDE::_NewWindow(HWND hwnd)
  2055. {
  2056. BOOL fSuccess = FALSE;
  2057. ENTERPROC(1, TEXT("NewWindow(hwnd=%08X)"), hwnd);
  2058. ASSERT(IS_VALID_HANDLE(hwnd, WND));
  2059. ENTER_IEDDE_CRIT;
  2060. WINITEM wi;
  2061. if (GetWinitemFromHwnd(hwnd, &wi) == FALSE)
  2062. {
  2063. CIEDDEThread *pidt = new CIEDDEThread();
  2064. if (pidt)
  2065. {
  2066. DDETHREADINFO dti = {0};
  2067. DWORD dwThreadID = GetCurrentThreadId();
  2068. WINITEM wi;
  2069. BOOL fCreatedDTI = FALSE;
  2070. if (_GetWinitemFromThread(dwThreadID, &wi))
  2071. {
  2072. wi.pidt->GetDdeThreadInfo(&dti);
  2073. }
  2074. else
  2075. {
  2076. LEAVE_IEDDE_CRIT;
  2077. _CreateDdeThreadInfo(&dti);
  2078. ENTER_IEDDE_CRIT;
  2079. fCreatedDTI = TRUE;
  2080. }
  2081. if (dti.dwDDEInst)
  2082. {
  2083. static DWORD dwNextWindowID = 1;
  2084. pidt->SetDdeThreadInfo(&dti);
  2085. wi.dwThreadID = dwThreadID;
  2086. wi.pidt = pidt;
  2087. wi.hwnd = hwnd;
  2088. wi.dwWindowID = dwNextWindowID++;
  2089. if (_AddWinitem(&wi))
  2090. {
  2091. //
  2092. // Now that we have a (partial) winitem in the winitem
  2093. // database, we can register our name service. If we
  2094. // registered any sooner, there is a risk that an app
  2095. // will try to connect to us while we are registering,
  2096. // and we will fail the connect because the winitem
  2097. // is not in the registry yet.
  2098. //
  2099. LEAVE_IEDDE_CRIT;
  2100. dti.hddNameService = DdeNameService(dti.dwDDEInst, dti.hszService, 0, DNS_REGISTER);
  2101. ENTER_IEDDE_CRIT;
  2102. //
  2103. // Now that we have hddNameService, we can update the
  2104. // winitem in the database.
  2105. //
  2106. if (dti.hddNameService)
  2107. {
  2108. pidt->SetDdeThreadInfo(&dti);
  2109. if (_UpdateWinitem(&wi))
  2110. {
  2111. fSuccess = TRUE;
  2112. }
  2113. else
  2114. {
  2115. TraceMsg(TF_WARNING, "IEDDE: _NewWindow unable to update a win item");
  2116. }
  2117. }
  2118. else
  2119. {
  2120. TraceMsg(TF_WARNING, "IEDDE: _NewWindow unable to register service");
  2121. }
  2122. }
  2123. else
  2124. {
  2125. TraceMsg(TF_WARNING, "IEDDE: _NewWindow could not append win item");
  2126. }
  2127. if (!fSuccess && fCreatedDTI)
  2128. {
  2129. LEAVE_IEDDE_CRIT;
  2130. _DestroyDdeThreadInfo(&dti);
  2131. ENTER_IEDDE_CRIT;
  2132. }
  2133. }
  2134. else
  2135. {
  2136. TraceMsg(TF_WARNING, "IEDDE: _NewWindow could not get/create dde thread info");
  2137. }
  2138. if (!fSuccess)
  2139. {
  2140. delete pidt;
  2141. }
  2142. }
  2143. else
  2144. {
  2145. TraceMsg(TF_WARNING, "IEDDE: _NewWindow could not create iedde thread object");
  2146. }
  2147. }
  2148. else
  2149. {
  2150. TraceMsg(TF_WARNING, "IEDDE: _NewWindow says window already registered?!?");
  2151. }
  2152. LEAVE_IEDDE_CRIT;
  2153. EXITPROC(1, TEXT("_NewWindow=%d"), fSuccess);
  2154. return fSuccess;
  2155. }
  2156. //
  2157. // _WindowDestroyed - Remove a browser window from the internal list
  2158. //
  2159. BOOL CIEDDE::_WindowDestroyed(HWND hwnd)
  2160. {
  2161. BOOL fSuccess = FALSE;
  2162. ENTERPROC(1, TEXT("_WindowDestroyed(hwnd=%08X)"), hwnd);
  2163. ENTER_IEDDE_CRIT;
  2164. WINITEM wi;
  2165. if (_DeleteWinitemByHwnd(hwnd, &wi))
  2166. {
  2167. fSuccess = TRUE;
  2168. ASSERT(wi.pidt);
  2169. WINITEM wiThread;
  2170. if (_GetWinitemFromThread(wi.dwThreadID, &wiThread) == FALSE)
  2171. {
  2172. if (wi.dwThreadID == GetCurrentThreadId())
  2173. {
  2174. DDETHREADINFO dti;
  2175. wi.pidt->GetDdeThreadInfo(&dti);
  2176. // Don't hold onto critical section while doing this...
  2177. LEAVE_IEDDE_CRIT;
  2178. _DestroyDdeThreadInfo(&dti);
  2179. ENTER_IEDDE_CRIT;
  2180. }
  2181. else
  2182. {
  2183. TraceMsg(TF_WARNING, "IEDDE: _WindowDestroyed called on wrong thread");
  2184. }
  2185. }
  2186. delete wi.pidt;
  2187. }
  2188. else
  2189. {
  2190. TraceMsg(TF_WARNING, "IEDDE: _WindowDestroyed could not find hwnd");
  2191. }
  2192. LEAVE_IEDDE_CRIT;
  2193. EXITPROC(1, TEXT("_WindowDestroyed=%d"), fSuccess);
  2194. return fSuccess;
  2195. }
  2196. //
  2197. // IEDDE_ functions are those exported for other parts of shdocvw to call.
  2198. // They pretty much just call the equivalent function in g_pIEDDE.
  2199. //
  2200. BOOL IEDDE_Initialize(void)
  2201. {
  2202. BOOL fRet = FALSE;
  2203. ENTERPROC(2, TEXT("IEDDE_Initialize()"));
  2204. if (g_pIEDDE == NULL)
  2205. {
  2206. g_pIEDDE = new CIEDDE;
  2207. if (g_pIEDDE)
  2208. {
  2209. fRet = g_pIEDDE->_Initialize();
  2210. }
  2211. else
  2212. {
  2213. TraceMsg(TF_WARNING, "IEDDE: IEDDE_Initialize could not allocate an IEDDE object");
  2214. }
  2215. }
  2216. else
  2217. {
  2218. TraceMsg(TF_WARNING, "IEDDE: IEDDE_Initialize says already initialized");
  2219. }
  2220. EXITPROC(2, TEXT("IEDDE_Initialize=%d"), fRet);
  2221. return fRet;
  2222. }
  2223. void IEDDE_Uninitialize(void)
  2224. {
  2225. ENTERPROC(2, TEXT("IEDDE_Uninitialize()"));
  2226. if (g_pIEDDE)
  2227. {
  2228. g_pIEDDE->_Uninitialize();
  2229. delete g_pIEDDE;
  2230. g_pIEDDE = NULL;
  2231. }
  2232. else
  2233. {
  2234. TraceMsg(TF_WARNING, "IEDDE: IEDDE_Uninitialize has no IEDDE object");
  2235. }
  2236. EXITPROC(2, TEXT("IEDDE_Uninitialize!"));
  2237. }
  2238. BOOL IEDDE_RunDelayedExecute()
  2239. {
  2240. if (g_pIEDDE)
  2241. {
  2242. g_pIEDDE->RunDelayedExecute();
  2243. }
  2244. else
  2245. {
  2246. TraceMsg(TF_WARNING, "IEDDE: IEDDE_RunDelayedExecute has no IEDDE object");
  2247. }
  2248. return TRUE;
  2249. }
  2250. void IEDDE_AutomationStarted(void)
  2251. {
  2252. ENTERPROC(2, TEXT("IEDDE_AutomationStarted()"));
  2253. if (g_pIEDDE)
  2254. {
  2255. g_pIEDDE->_AutomationStarted();
  2256. }
  2257. else
  2258. {
  2259. TraceMsg(TF_WARNING, "IEDDE: IEDDE_AutomationStarted has no IEDDE object");
  2260. }
  2261. EXITPROC(2, TEXT("IEDDE_AutomationStarted!"));
  2262. }
  2263. HRESULT IEDDE_BeforeNavigate(LPCWSTR pwszURL, BOOL *pfCanceled)
  2264. {
  2265. HRESULT hr = E_FAIL;
  2266. ENTERPROC(2, TEXT("IEDDE_BeforeNavigate(pwszURL=%08X,pfCanceled=%08X)"), pwszURL, pfCanceled);
  2267. if (g_pIEDDE)
  2268. {
  2269. LPCTSTR pszURL;
  2270. pszURL = pwszURL;
  2271. if (pszURL)
  2272. {
  2273. hr = g_pIEDDE->_BeforeNavigate(pszURL, pfCanceled);
  2274. }
  2275. }
  2276. else
  2277. {
  2278. TraceMsg(TF_WARNING, "IEDDE: IEDDE_BeforeNavigate has no IEDDE object");
  2279. }
  2280. EXITPROC(2, TEXT("IEDDE_BeforeNavigate=%08X"), hr);
  2281. return hr;
  2282. }
  2283. HRESULT IEDDE_AfterNavigate(LPCWSTR pwszURL, HWND hwnd)
  2284. {
  2285. HRESULT hr = E_FAIL;
  2286. ENTERPROC(2, TEXT("IEDDE_AfterNavigate(pwszURL=%08X,hwnd=%08X)"), pwszURL, hwnd);
  2287. if (g_pIEDDE)
  2288. {
  2289. LPCTSTR pszURL;
  2290. pszURL = pwszURL;
  2291. if (pszURL)
  2292. {
  2293. hr = g_pIEDDE->_AfterNavigate(pszURL, hwnd);
  2294. }
  2295. }
  2296. else
  2297. {
  2298. TraceMsg(TF_WARNING, "IEDDE: IEDDE_AfterNavigate has no IEDDE object");
  2299. }
  2300. EXITPROC(2, TEXT("IEDDE_AfterNavigate=%08X"), hr);
  2301. return hr;
  2302. }
  2303. BOOL IEDDE_NewWindow(HWND hwnd)
  2304. {
  2305. BOOL fRet = FALSE;
  2306. ENTERPROC(2, TEXT("IEDDE_NewWindow(hwnd=%08X)"), hwnd);
  2307. if (g_pIEDDE)
  2308. {
  2309. fRet = g_pIEDDE->_NewWindow(hwnd);
  2310. }
  2311. else
  2312. {
  2313. TraceMsg(TF_WARNING, "IEDDE: IEDDE_NewWindow has no IEDDE object");
  2314. }
  2315. EXITPROC(2, TEXT("IEDDE_NewWindow=%d"), fRet);
  2316. return fRet;
  2317. }
  2318. BOOL IEDDE_WindowDestroyed(HWND hwnd)
  2319. {
  2320. BOOL fRet = FALSE;
  2321. ENTERPROC(2, TEXT("IEDDE_WindowDestroyed(hwnd=%08X)"), hwnd);
  2322. if (g_pIEDDE)
  2323. {
  2324. fRet = g_pIEDDE->_WindowDestroyed(hwnd);
  2325. }
  2326. else
  2327. {
  2328. TraceMsg(TF_WARNING, "IEDDE: IEDDE_WindowDestroyed has no IEDDE object");
  2329. }
  2330. EXITPROC(2, TEXT("IEDDE_WindowDestroyed=%d"), fRet);
  2331. return fRet;
  2332. }
  2333. #ifdef DEBUG
  2334. //
  2335. // Move g_dwIEDDETrace into ccshell.ini to prevent recompiles.
  2336. //
  2337. DWORD g_dwIEDDETrace = 0;
  2338. static DWORD g_dwIndent = 0;
  2339. static const TCHAR c_szDotDot[] = TEXT("..");
  2340. #define MAX_INDENTATION_VALUE 0x10
  2341. void EnterProc(DWORD dwTraceLevel, LPTSTR szFmt, ...)
  2342. {
  2343. TCHAR szOutput[1000];
  2344. va_list arglist;
  2345. if (dwTraceLevel <= g_dwIEDDETrace)
  2346. {
  2347. szOutput[0] = TEXT('\0');
  2348. for (DWORD i=0; i<g_dwIndent; i++)
  2349. {
  2350. StrCatBuff(szOutput, c_szDotDot, ARRAYSIZE(szOutput));
  2351. }
  2352. va_start(arglist, szFmt);
  2353. wvnsprintf(szOutput + lstrlen(szOutput), ARRAYSIZE(szOutput) - lstrlen(szOutput), szFmt, arglist);
  2354. va_end(arglist);
  2355. TraceMsg(TF_ALWAYS, "%s", szOutput);
  2356. // This value can get out of hand if EnterProc and ExitProc
  2357. // calls do not match. This can trash the stack.
  2358. if(g_dwIndent < MAX_INDENTATION_VALUE)
  2359. g_dwIndent++;
  2360. }
  2361. }
  2362. void ExitProc(DWORD dwTraceLevel, LPTSTR szFmt, ...)
  2363. {
  2364. TCHAR szOutput[1000];
  2365. va_list arglist;
  2366. if (dwTraceLevel <= g_dwIEDDETrace)
  2367. {
  2368. // This can happen if the EnterProc and
  2369. // ExitProc calls do not match.
  2370. if(g_dwIndent > 0)
  2371. g_dwIndent--;
  2372. szOutput[0] = TEXT('\0');
  2373. for (DWORD i=0; i<g_dwIndent; i++)
  2374. {
  2375. StrCatBuff(szOutput, c_szDotDot, ARRAYSIZE(szOutput));
  2376. }
  2377. va_start(arglist, szFmt);
  2378. wvnsprintf(szOutput + lstrlen(szOutput), ARRAYSIZE(szOutput) - lstrlen(szOutput), szFmt, arglist);
  2379. va_end(arglist);
  2380. TraceMsg(TF_ALWAYS, "%s", szOutput);
  2381. }
  2382. }
  2383. #endif