mtbrowser.cpp 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611
  1. #include "./mtbrowser.h"
  2. #include <exdispid.h>
  3. #define QUIT_FORCE 0x00FF
  4. #define THREAD_QUITING 0x0001
  5. #define THREAD_COMINIT 0x1000
  6. #define MEMMMGR_RECALLOCSTEP 8
  7. #define GetThreadBrowserInstance() ((HTMLContainer2*)TlsGetValue(threadStorage))
  8. typedef struct _THREAD_START_PARAM
  9. {
  10. HANDLE hEvent;
  11. MTBROWSER *pmtb;
  12. } THREAD_START_PARAM;
  13. typedef struct _MEMREC
  14. {
  15. HANDLE handle;
  16. FREEPROC freeproc;
  17. } MEMREC;
  18. typedef struct _MEMMNGR
  19. {
  20. CRITICAL_SECTION cs;
  21. MEMREC *pRec;
  22. INT cCount;
  23. INT cAlloc;
  24. } MEMMNGR;
  25. typedef struct _APCPARAM
  26. {
  27. MEMMNGR *pmm;
  28. VARIANTARG *pArgs;
  29. INT cArgs;
  30. HWND hwndNotify;
  31. UINT uMsgNotify;
  32. INT nNotifyCode;
  33. APCPROC fnAPC;
  34. HANDLE hThread;
  35. } APCPARAM;
  36. typedef struct _CALLBACKPARAM
  37. {
  38. HWND hwndNotify;
  39. UINT uMsgNotify;
  40. BOOL bDestroyed;
  41. BOOL bQuiting;
  42. BOOL bReady;
  43. } CALLBACKPARAM;
  44. // forward declarations
  45. static DWORD CALLBACK BrowserThread(LPVOID param);
  46. static HRESULT MTBrowser_Quit(HTMLContainer2 *pContainer);
  47. static BOOL MemRec_Add(MEMMNGR *pmm, void *pMem, FREEPROC fnFreeProc);
  48. static BOOL MemRec_Free(MEMMNGR *pmm, void *pMem);
  49. static APCPARAM *AllocAPCParam(MTBROWSER *pmtb, INT cArgs, INT nNotifyCode, APCPROC fnAPC);
  50. static void CALLBACK FreeAPCParam(void *pMem);
  51. // APC
  52. static void CALLBACK APC_FunctionCall(ULONG_PTR param);
  53. static void CALLBACK APC_NavigateToName(HTMLContainer2 *pContainer, VARIANTARG *pArgs, INT cArgs, LPARAM *pResult);
  54. static void CALLBACK APC_SetLocation(HTMLContainer2 *pContainer, VARIANTARG *pArgs, INT cArgs, LPARAM *pResult);
  55. static void CALLBACK APC_Refresh2(HTMLContainer2 *pContainer, VARIANTARG *pArgs, INT cArgs, LPARAM *pResult);
  56. static DWORD threadStorage = TLS_OUT_OF_INDEXES;
  57. BOOL MTBrowser_Init(MTBROWSER *pmtb)
  58. {
  59. if (!pmtb) return FALSE;
  60. ZeroMemory(pmtb, sizeof(MTBROWSER));
  61. if (TLS_OUT_OF_INDEXES == threadStorage)
  62. {
  63. threadStorage = TlsAlloc();
  64. if (TLS_OUT_OF_INDEXES == threadStorage) return FALSE;
  65. }
  66. return TRUE;
  67. }
  68. BOOL MTBrowser_Clear(MTBROWSER *pmtb)
  69. {
  70. if (pmtb)
  71. {
  72. if (pmtb->hThread) CloseHandle(pmtb->hThread);
  73. if (pmtb->hMemMngr)
  74. {
  75. MEMMNGR *pmm;
  76. pmm = (MEMMNGR*)pmtb->hMemMngr;
  77. EnterCriticalSection(&pmm->cs);
  78. for(int i = 0; i < pmm->cCount; i++)
  79. {
  80. if (pmm->pRec[i].handle)
  81. {
  82. (pmm->pRec[i].freeproc) ? pmm->pRec[i].freeproc(pmm->pRec[i].handle) : free(pmm->pRec[i].handle);
  83. }
  84. }
  85. pmm->cCount = 0;
  86. LeaveCriticalSection(&pmm->cs);
  87. DeleteCriticalSection(&pmm->cs);
  88. free(pmtb->hMemMngr);
  89. }
  90. ZeroMemory(pmtb, sizeof(MTBROWSER));
  91. }
  92. return TRUE;
  93. }
  94. BOOL MTBrowser_Start(MTBROWSER *pmtb, HTMLContainer2 *pContainer, UINT uMsgNotify)
  95. {
  96. THREAD_START_PARAM param = {0};
  97. if (!pmtb || !pContainer || TLS_OUT_OF_INDEXES == threadStorage) return FALSE;
  98. pmtb->hMemMngr = calloc(1, sizeof(MEMMNGR));
  99. if (!pmtb->hMemMngr) return FALSE;
  100. InitializeCriticalSection(&((MEMMNGR*)pmtb->hMemMngr)->cs);
  101. param.hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
  102. param.pmtb = pmtb;
  103. pmtb->uMsgNotify = uMsgNotify;
  104. pmtb->pContainer = pContainer;
  105. pmtb->hThread = CreateThread(NULL, 0, BrowserThread, (LPVOID)&param, 0, &pmtb->dwThreadId);
  106. if (pmtb->hThread)
  107. {
  108. WaitForSingleObject(param.hEvent, INFINITE);
  109. SetThreadPriority(pmtb->hThread, THREAD_PRIORITY_NORMAL);
  110. }
  111. CloseHandle(param.hEvent);
  112. return (NULL != pmtb->hThread);
  113. }
  114. BOOL MTBrowser_Kill(MTBROWSER *pmtb, UINT nTerminateDelay)
  115. {
  116. MSG msg;
  117. if (pmtb)
  118. {
  119. pmtb->bQuiting = TRUE;
  120. if (pmtb && pmtb->hThread)
  121. {
  122. PostThreadMessage(pmtb->dwThreadId, WM_QUIT, QUIT_FORCE, 0L);
  123. while(WAIT_TIMEOUT == WaitForSingleObject(pmtb->hThread, 0))
  124. {
  125. DWORD dwStatus;
  126. dwStatus = MsgWaitForMultipleObjectsEx(1, &pmtb->hThread, nTerminateDelay, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
  127. if (WAIT_OBJECT_0 + 1 == dwStatus || WAIT_OBJECT_0 == dwStatus)
  128. {
  129. while (PeekMessageW(&msg, NULL, 0xc0d6, 0xc0d6, PM_NOREMOVE)) if (NULL == msg.hwnd) DispatchMessageW(&msg);
  130. }
  131. else if (WAIT_TIMEOUT == dwStatus)
  132. {
  133. TerminateThread(pmtb->hThread, 3);
  134. break;
  135. }
  136. }
  137. CloseHandle(pmtb->hThread);
  138. pmtb->hThread = NULL;
  139. }
  140. return TRUE;
  141. }
  142. return FALSE;
  143. }
  144. BOOL MTBrowser_QuitAPC(MTBROWSER *pmtb)
  145. {
  146. if (!pmtb) return FALSE;
  147. if (pmtb->bQuiting) return TRUE;
  148. pmtb->bQuiting = (pmtb->dwThreadId && PostThreadMessage(pmtb->dwThreadId, WM_QUIT, 0, 0L));
  149. return pmtb->bQuiting;
  150. }
  151. BOOL MTBrowser_NavigateToNameAPC(MTBROWSER *pmtb, LPCWSTR pszURL, UINT fFlags)
  152. {
  153. HAPC hAPC;
  154. VARIANTARG *pArgs;
  155. hAPC = MTBrowser_InitializeAPC(pmtb, 2, MTBC_APC_NAVIGATE, APC_NavigateToName, &pArgs);
  156. if (!hAPC) return FALSE;
  157. pArgs[0].vt = VT_BSTR;
  158. pArgs[0].bstrVal= SysAllocString(pszURL);
  159. pArgs[1].vt = VT_I4;
  160. pArgs[1].intVal = fFlags;
  161. return MTBrowser_CallAPC(hAPC);
  162. }
  163. BOOL MTBrowser_SetLocationAPC(MTBROWSER *pmtb, RECT *pRect)
  164. {
  165. HAPC hAPC;
  166. VARIANTARG *pArgs;
  167. hAPC = MTBrowser_InitializeAPC(pmtb, 4, MTBC_APC_SETLOCATION, APC_SetLocation, &pArgs);
  168. if (!hAPC) return FALSE;
  169. pArgs[0].vt = VT_I4;
  170. pArgs[0].intVal = pRect->left;
  171. pArgs[1].vt = VT_I4;
  172. pArgs[1].intVal = pRect->top;
  173. pArgs[2].vt = VT_I4;
  174. pArgs[2].intVal = pRect->right - pRect->left;
  175. pArgs[3].vt = VT_I4;
  176. pArgs[3].intVal = pRect->bottom - pRect->top;
  177. return MTBrowser_CallAPC(hAPC);
  178. }
  179. BOOL MTBrowser_Refresh2APC(MTBROWSER *pmtb, INT nRefreshMode)
  180. {
  181. HAPC hAPC;
  182. VARIANTARG *pArgs;
  183. hAPC = MTBrowser_InitializeAPC(pmtb, 1, MTBC_APC_REFRESH2, APC_Refresh2, &pArgs);
  184. if (!hAPC) return FALSE;
  185. pArgs[0].vt = VT_I4;
  186. pArgs[0].intVal = nRefreshMode;
  187. return MTBrowser_CallAPC(hAPC);
  188. }
  189. HAPC MTBrowser_InitializeAPC(MTBROWSER *pmtb, INT nCount, UINT nCmdCode, APCPROC fnAPC, VARIANTARG **pArgs)
  190. {
  191. APCPARAM *pParam;
  192. if (!pmtb || pmtb->bQuiting || !pmtb->hThread) return FALSE;
  193. pParam = AllocAPCParam(pmtb, nCount, nCmdCode, fnAPC);
  194. if (pParam && pArgs) *pArgs = pParam->pArgs;
  195. return (HAPC) pParam;
  196. }
  197. BOOL MTBrowser_CallAPC(HAPC hAPC)
  198. {
  199. BOOL result;
  200. if (!hAPC) return FALSE;
  201. result = QueueUserAPC(APC_FunctionCall, ((APCPARAM*)hAPC)->hThread, (ULONG_PTR)hAPC);
  202. if (!result) MemRec_Free(((APCPARAM*)hAPC)->pmm, hAPC);
  203. return result;
  204. }
  205. BOOL MTBrowser_AddMemRec(MTBROWSER *pmtb, void *pMem, FREEPROC fnFreeProc)
  206. {
  207. return (pmtb && pmtb->hMemMngr) ? MemRec_Add((MEMMNGR*)pmtb->hMemMngr, pMem, fnFreeProc) : FALSE;
  208. }
  209. BOOL MTBrowser_FreeMemRec(MTBROWSER *pmtb, void *pMem)
  210. {
  211. return (pmtb && pmtb->hMemMngr) ? MemRec_Free((MEMMNGR*)pmtb->hMemMngr, pMem) : FALSE;
  212. }
  213. static BOOL MemRec_Add(MEMMNGR *pmm, void *pMem, FREEPROC fnFreeProc)
  214. {
  215. if (!pmm || !pMem) return FALSE;
  216. EnterCriticalSection(&pmm->cs);
  217. if (pmm->cCount == pmm->cAlloc)
  218. {
  219. LPVOID pData;
  220. pData = realloc(pmm->pRec, sizeof(MEMREC)*(pmm->cCount + MEMMMGR_RECALLOCSTEP));
  221. if (!pData)
  222. {
  223. LeaveCriticalSection(&pmm->cs);
  224. return FALSE;
  225. }
  226. pmm->pRec = (MEMREC*)pData;
  227. pmm->cAlloc = pmm->cCount + MEMMMGR_RECALLOCSTEP;
  228. }
  229. pmm->pRec[pmm->cCount].handle = pMem;
  230. pmm->pRec[pmm->cCount].freeproc = fnFreeProc;
  231. pmm->cCount++;
  232. LeaveCriticalSection(&pmm->cs);
  233. return TRUE;
  234. }
  235. static BOOL MemRec_Free(MEMMNGR *pmm, void *pMem)
  236. {
  237. INT index;
  238. MEMREC rec;
  239. if (!pmm || !pMem) return FALSE;
  240. EnterCriticalSection(&pmm->cs);
  241. ZeroMemory(&rec, sizeof(MEMREC));
  242. for(index = 0; index < pmm->cCount; index++)
  243. {
  244. if (pmm->pRec[index].handle == pMem)
  245. {
  246. rec.freeproc= pmm->pRec[index].freeproc;
  247. rec.handle = pmm->pRec[index].handle;
  248. break;
  249. }
  250. }
  251. if (index < (pmm->cCount -1)) MoveMemory(&pmm->pRec[index], &pmm->pRec[index + 1], sizeof(MEMREC)*(pmm->cCount - index - 1));
  252. if (index < pmm->cCount) pmm->cCount--;
  253. if(rec.handle)
  254. {
  255. (rec.freeproc) ? rec.freeproc(rec.handle) : free(rec.handle);
  256. }
  257. LeaveCriticalSection(&pmm->cs);
  258. return (NULL != rec.handle);
  259. }
  260. #define POSTNOTIFY(_hwnd, _msg, _code, _param) ((_msg && IsWindow(_hwnd)) ? PostMessageW(_hwnd, _msg, (WPARAM)_code, (LPARAM)_param) : FALSE)
  261. static BOOL CALLBACK OnBrowserEvent(HTMLContainer2 *pContainer, DISPID dispId, DISPPARAMS FAR *pDispParams, LPVOID pUser)
  262. {
  263. CALLBACKPARAM *pcb;
  264. pcb = (CALLBACKPARAM*)pUser;
  265. if (!pcb) return FALSE;
  266. switch(dispId)
  267. {
  268. case DISPID_DESTRUCTOR:
  269. pcb->bDestroyed = TRUE;
  270. PostThreadMessage(GetCurrentThreadId(), WM_NULL, 0, 0L);
  271. break;
  272. case DISPID_NAVIGATECOMPLETE2:
  273. if (pcb->bReady)
  274. {
  275. }
  276. else
  277. {
  278. DWORD_PTR dwRedrawOFF;
  279. HWND hwndParent;
  280. hwndParent = pContainer->GetParentHWND();
  281. if (hwndParent) SendMessageTimeout(hwndParent, WM_SETREDRAW, FALSE, 0L, SMTO_NORMAL, 100, &dwRedrawOFF);
  282. pContainer->SetLocation(-2000, 0, 100, 100);
  283. if (hwndParent) SendMessageTimeout(hwndParent, WM_SETREDRAW, TRUE, 0L, SMTO_NORMAL, 100, &dwRedrawOFF);
  284. }
  285. break;
  286. case DISPID_DOCUMENTCOMPLETE:
  287. {
  288. HRESULT hr;
  289. IUnknown *pUnk, *pUnkDisp;
  290. BOOL bDocReady;
  291. bDocReady = FALSE;
  292. hr = pContainer->GetIUnknown(&pUnk);
  293. if (SUCCEEDED(hr))
  294. {
  295. hr = pDispParams->rgvarg[1].pdispVal->QueryInterface(IID_IUnknown, (void**)&pUnkDisp);
  296. if (SUCCEEDED(hr)) pUnkDisp->Release();
  297. if (pUnk == pUnkDisp) bDocReady = TRUE;
  298. if (!pcb->bReady && pDispParams->rgvarg[0].pvarVal->bstrVal &&
  299. 0 == lstrcmpW(L"about:blank", pDispParams->rgvarg[0].pvarVal->bstrVal))
  300. {
  301. pcb->bReady = TRUE;
  302. POSTNOTIFY(pcb->hwndNotify, pcb->uMsgNotify, MTBC_READY, (LPARAM)pContainer);
  303. break;
  304. }
  305. }
  306. if (pcb->bReady) POSTNOTIFY(pcb->hwndNotify, pcb->uMsgNotify, MTBC_DOCUMENTCOMPLETE, bDocReady);
  307. }
  308. }
  309. return pcb->bQuiting;
  310. }
  311. static DWORD CALLBACK BrowserThread(LPVOID param)
  312. {
  313. HRESULT hr;
  314. HTMLContainer2 *pInstance;
  315. DWORD dwInterval;
  316. UINT uState;
  317. MSG msg;
  318. CALLBACKPARAM cbParam;
  319. uState = 0;
  320. TlsSetValue(threadStorage, 0);
  321. pInstance = ((THREAD_START_PARAM*)param)->pmtb->pContainer;
  322. ZeroMemory(&cbParam, sizeof(CALLBACKPARAM));
  323. cbParam.uMsgNotify = ((THREAD_START_PARAM*)param)->pmtb->uMsgNotify;
  324. cbParam.hwndNotify = pInstance->GetParentHWND();
  325. pInstance->RegisterBrowserEventCB(OnBrowserEvent, (LPVOID)&cbParam);
  326. ((THREAD_START_PARAM*)param)->pmtb->hwndNotify = cbParam.hwndNotify;
  327. SetEvent(((THREAD_START_PARAM*)param)->hEvent);
  328. hr = OleInitialize(NULL);//hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
  329. if (SUCCEEDED(hr))
  330. {
  331. uState |= THREAD_COMINIT;
  332. hr = pInstance->Initialize();
  333. if(SUCCEEDED(hr)) TlsSetValue(threadStorage, pInstance);
  334. else
  335. {
  336. pInstance->Finish();
  337. pInstance->Release();
  338. }
  339. }
  340. // force message queue
  341. PeekMessageW(&msg, NULL, WM_USER, WM_USER, PM_NOREMOVE);
  342. if (FAILED(hr) || !IsWindow(cbParam.hwndNotify))
  343. {
  344. TlsSetValue(threadStorage, 0);
  345. pInstance->Finish();
  346. pInstance->Release();
  347. }
  348. else
  349. {
  350. pInstance->NavigateToName(L"about:blank", 0);
  351. }
  352. dwInterval = INFINITE;
  353. while (!cbParam.bDestroyed)
  354. {
  355. DWORD dwStatus = MsgWaitForMultipleObjectsEx(0, NULL, dwInterval, QS_ALLINPUT, MWMO_ALERTABLE | MWMO_INPUTAVAILABLE);
  356. if (WAIT_OBJECT_0 == dwStatus)
  357. {
  358. while (PeekMessageW(&msg, NULL, 0, 0, PM_REMOVE))
  359. {
  360. if (WM_QUIT == msg.message)
  361. {
  362. cbParam.bQuiting = TRUE;
  363. TlsSetValue(threadStorage, 0);
  364. if (QUIT_FORCE == msg.wParam)
  365. {
  366. if (!cbParam.bDestroyed)
  367. {
  368. pInstance->Finish();
  369. while(pInstance->Release() > 0);
  370. }
  371. break;
  372. }
  373. else if (0 == (THREAD_QUITING & uState) && SUCCEEDED(MTBrowser_Quit(pInstance)))
  374. {
  375. uState |= THREAD_QUITING;
  376. dwInterval = 200;
  377. }
  378. POSTNOTIFY(cbParam.hwndNotify, cbParam.uMsgNotify, MTBC_APC_QUIT, (LPARAM)(THREAD_QUITING & uState));
  379. }
  380. else if ((WM_KEYFIRST > msg.message || WM_KEYLAST < msg.message ||
  381. (THREAD_QUITING & uState) || !pInstance->TranslateKey(&msg)) &&
  382. !IsDialogMessageW(cbParam.hwndNotify, &msg))
  383. {
  384. TranslateMessage(&msg);
  385. DispatchMessageW(&msg);
  386. }
  387. }
  388. }
  389. else if (WAIT_TIMEOUT == dwStatus) // quiting - check readystatus
  390. {
  391. if (!cbParam.bDestroyed)
  392. {
  393. READYSTATE state;
  394. IWebBrowser2 *pWeb2;
  395. hr = pInstance->GetIWebBrowser2(&pWeb2);
  396. if (SUCCEEDED(hr))
  397. {
  398. hr = pWeb2->get_ReadyState(&state);
  399. pWeb2->Release();
  400. }
  401. else state = READYSTATE_UNINITIALIZED;
  402. if (FAILED(hr) || READYSTATE_UNINITIALIZED == state || READYSTATE_INTERACTIVE <= state)
  403. {
  404. pInstance->Finish();
  405. pInstance->Release();
  406. }
  407. }
  408. }
  409. }
  410. if (THREAD_COMINIT & uState) OleUninitialize();//CoUninitialize();
  411. POSTNOTIFY(cbParam.hwndNotify, cbParam.uMsgNotify, MTBC_DESTROYED, (LPARAM)pInstance);
  412. return 0;
  413. }
  414. static HRESULT MTBrowser_Quit(HTMLContainer2 *pContainer)
  415. {
  416. HRESULT hr;
  417. IWebBrowser2 *pWeb2;
  418. hr = pContainer->GetIWebBrowser2(&pWeb2);
  419. if (SUCCEEDED(hr))
  420. {
  421. hr = pWeb2->Stop();
  422. pWeb2->Release();
  423. if (SUCCEEDED(hr)) hr = pContainer->NavigateToName(L"about:blank", navNoHistory | navNoReadFromCache | navNoWriteToCache);
  424. }
  425. return hr;
  426. }
  427. static APCPARAM* AllocAPCParam(MTBROWSER *pmtb, INT cArgs, INT nNotifyCode, APCPROC fnAPC)
  428. {
  429. if (!pmtb || !pmtb->hMemMngr || !fnAPC) return NULL;
  430. APCPARAM *pParam = (APCPARAM*)calloc(1, sizeof(APCPARAM));
  431. if (!pParam) return NULL;
  432. if (cArgs)
  433. {
  434. INT i;
  435. pParam->pArgs = (VARIANTARG*)calloc(cArgs, sizeof(VARIANTARG));
  436. if (!pParam->pArgs)
  437. {
  438. free(pParam);
  439. return NULL;
  440. }
  441. for (i = 0; i < cArgs; i++) VariantInit(&pParam->pArgs[i]);
  442. }
  443. else pParam->pArgs = NULL;
  444. pParam->cArgs = cArgs;
  445. pParam->pmm = (MEMMNGR*)pmtb->hMemMngr;
  446. pParam->hwndNotify = pmtb->hwndNotify;
  447. pParam->uMsgNotify = pmtb->uMsgNotify;
  448. pParam->nNotifyCode = nNotifyCode;
  449. pParam->fnAPC = fnAPC;
  450. pParam->hThread = pmtb->hThread;
  451. if (!MemRec_Add(pParam->pmm, pParam, FreeAPCParam))
  452. {
  453. FreeAPCParam(pParam);
  454. pParam = NULL;
  455. }
  456. return pParam;
  457. }
  458. static void CALLBACK FreeAPCParam(void *pMem)
  459. {
  460. if (pMem)
  461. {
  462. APCPARAM* pParam;
  463. pParam = (APCPARAM*)pMem;
  464. if (pParam->pArgs)
  465. {
  466. for(INT i = 0; i < pParam->cArgs; i++) VariantClear(&pParam->pArgs[i]);
  467. free(pParam->pArgs);
  468. }
  469. free(pMem);
  470. }
  471. }
  472. static void CALLBACK APC_FunctionCall(ULONG_PTR param)
  473. {
  474. LPARAM result;
  475. APCPARAM *pParam;
  476. pParam = (APCPARAM*)param;
  477. if (!pParam) return;
  478. HTMLContainer2 *pContainer;
  479. pContainer = GetThreadBrowserInstance();
  480. if (pContainer)
  481. {
  482. result = 0L;
  483. if (pParam->fnAPC) pParam->fnAPC(pContainer, pParam->pArgs, pParam->cArgs, &result);
  484. if (pParam->nNotifyCode && pParam->hwndNotify && IsWindow(pParam->hwndNotify))
  485. {
  486. PostMessageW(pParam->hwndNotify, pParam->uMsgNotify, pParam->nNotifyCode, result);
  487. }
  488. }
  489. MemRec_Free(pParam->pmm, pParam);
  490. }
  491. static void CALLBACK APC_NavigateToName(HTMLContainer2 *pContainer, VARIANTARG *pArgs, INT cArgs, LPARAM *pResult)
  492. {
  493. *pResult = (2 == cArgs) ? pContainer->NavigateToName(pArgs[0].bstrVal, pArgs[1].intVal) : E_INVALIDARG;
  494. }
  495. static void CALLBACK APC_SetLocation(HTMLContainer2 *pContainer, VARIANTARG *pArgs, INT cArgs, LPARAM *pResult)
  496. {
  497. *pResult = (4 == cArgs) ? pContainer->SetLocation(pArgs[0].intVal, pArgs[1].intVal, pArgs[2].intVal, pArgs[3].intVal) : E_INVALIDARG;
  498. }
  499. static void CALLBACK APC_Refresh2(HTMLContainer2 *pContainer, VARIANTARG *pArgs, INT cArgs, LPARAM *pResult)
  500. {
  501. if (1 != cArgs) *pResult = E_INVALIDARG;
  502. else
  503. {
  504. HRESULT hr;
  505. IWebBrowser2 *pWeb2;
  506. hr = pContainer->GetIWebBrowser2(&pWeb2);
  507. if (SUCCEEDED(hr))
  508. {
  509. hr = pWeb2->Refresh2(&pArgs[0]);
  510. pWeb2->Release();
  511. }
  512. *pResult = (LPARAM)hr;
  513. }
  514. }