CHtmlView의 C++에서 생성한 JScript를 모든 Frame에 대해 Inject하여 실행하기
2010. 12. 8. 16:59 in 프로그래밍/Let's Share it

2010/11/03 - [프로그래밍/Let's Share it] - CHtmlView의 C++에서 생성한 JScript를 Inject하여 실행하기
에서 version up된 내용을 다시 공유합니다.
이전 포스트에서 CHtmlView로 html에 jscript를 inject하는 방법을 알아보았는데, 문제는 frameset이 지원되지 않는다는 점입니다. 즉, a.html(=1.html + 2.html)로 되는 경우, 1.html/2.html에서는 jscript가 inject되지 않습니다. 따라서, frame을 enum하여 모든 frame에서 가능토록 하고, recursive 사용으로 인한 depth cut-off까지 구현된것을 공유합니다.
사용법은 간단한데, CHtmlView의 DocumentComplete와 NavigateComplete2 시기에,
에서 version up된 내용을 다시 공유합니다.
이전 포스트에서 CHtmlView로 html에 jscript를 inject하는 방법을 알아보았는데, 문제는 frameset이 지원되지 않는다는 점입니다. 즉, a.html(=1.html + 2.html)로 되는 경우, 1.html/2.html에서는 jscript가 inject되지 않습니다. 따라서, frame을 enum하여 모든 frame에서 가능토록 하고, recursive 사용으로 인한 depth cut-off까지 구현된것을 공유합니다.
사용법은 간단한데, CHtmlView의 DocumentComplete와 NavigateComplete2 시기에,
InjectJScriptAllFrame(this, TEXT("function XXXX() {....}"), 10);
과 같이 사용하면 됩니다.
즉, MAX Frame Depth를 10으로 준 경우이며,
만약 10개가 넘는 경우, Navigate가 중단되며, 꼭 계층적으로 10개의 Frame까지 표시되는 것은 아니니,
주의하시기 바랍니다.
view plain하면 좀더 코드를 좀더 잘 확인할 수 있습니다.
즉, MAX Frame Depth를 10으로 준 경우이며,
만약 10개가 넘는 경우, Navigate가 중단되며, 꼭 계층적으로 10개의 Frame까지 표시되는 것은 아니니,
주의하시기 바랍니다.
view plain하면 좀더 코드를 좀더 잘 확인할 수 있습니다.
- HRESULT InjectJScriptAllFrame(IN CHtmlView* pcWnd, IN LPCTSTR lpszJScript, IN INT nMaxRecurseFrame)
- {
- HRESULT hr = S_OK;
- BOOL bStackOverflow = FALSE;
- IHTMLDocument2* pIHtmlDocument2 = NULL;
- if ((NULL == pcWnd) || (NULL == lpszJScript))
- {
- hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
- ASSERT(FALSE);
- goto FINAL;
- }
- if (NULL == pcWnd->GetHtmlDocument())
- {
- hr = HRESULT_FROM_WIN32(ERROR_NOT_READY);
- ASSERT(FALSE);
- goto FINAL;
- }
- hr = pcWnd->GetHtmlDocument()->QueryInterface(IID_IHTMLDocument2, (VOID**)&pIHtmlDocument2);
- if (SUCCEEDED(hr))
- {
- if (NULL == pIHtmlDocument2)
- {
- hr = HRESULT_FROM_WIN32(ERROR_INTERNAL_ERROR);
- ASSERT(FALSE);
- goto FINAL;
- }
- // HtmlDocument를 Frame 별로 recursive하게 JScript를 inject한다.
- // 만약, Frame이 MAX가 되었다면, hr은 HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW)가 리턴된다.
- hr = InjectJScriptByDocumentRecurse(pIHtmlDocument2, lpszJScript, nMaxRecurseFrame, 0, &bStackOverflow);
- if (HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW) == hr)
- {
- // Stack overflow인 경우에는 stop~!
- pcWnd->Stop();
- }
- }
- FINAL:
- if (NULL != pIHtmlDocument2)
- {
- pIHtmlDocument2->Release();
- pIHtmlDocument2 = NULL;
- }
- return hr;
- }
- HRESULT InjectJScriptByDocumentRecurse(IN IHTMLDocument2* pIHtmlDocument2, IN LPCTSTR lpszJScript, IN INT nMaxRecurseFrame, IN INT nCurDepth, OUT LPBOOL pbStackOverflow)
- {
- HRESULT hr = S_OK;
- HRESULT hr2 = S_OK;
- LONG nFrameCount = 0;
- LONG i = 0;
- VARIANT varIndex = {0,};
- VARIANT varDispWin = {0,};
- BSTR bstrScript = {0,};
- BSTR bstrElementType = {0,};
- BSTR bstrInsertWhere = {0,};
- IHTMLElement* pIHtmlElement = NULL;
- IHTMLElement2* pIHtmlElement2 = NULL;
- IHTMLElement* pIHtmlElementScript = NULL;
- IHTMLScriptElement* pIHtmlScript = NULL;
- IHTMLFramesCollection2* pIHtmlFramesCollection = NULL;
- IHTMLWindow2* pIHtmlWindow = NULL;
- IHTMLDocument2* pIHtmlDocument2Frame = NULL;
- if ((NULL == pIHtmlDocument2) || (NULL == lpszJScript) || (NULL == pbStackOverflow))
- {
- hr = HRESULT_FROM_WIN32(ERROR_INVALID_PARAMETER);
- goto FINAL;
- }
- if (nCurDepth >= nMaxRecurseFrame)
- {
- hr = HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW);
- *pbStackOverflow = TRUE;
- goto FINAL;
- }
- if (TRUE == *pbStackOverflow)
- {
- hr = HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW);
- goto FINAL;
- }
- // insertAdjacentElement에 들어갈 Param을 결정한다.
- bstrScript = ::SysAllocString(T2COLE(lpszJScript));
- bstrElementType = ::SysAllocString(T2COLE(TEXT("script")));
- bstrInsertWhere = ::SysAllocString(T2COLE(TEXT("afterBegin")));
- hr = pIHtmlDocument2->get_body(&pIHtmlElement);
- if ((FAILED(hr)) || (NULL == pIHtmlElement))
- {
- if ((SUCCEEDED(hr)) && (NULL == pIHtmlElement))
- {
- hr = HRESULT_FROM_WIN32(ERROR_NOT_READY);
- goto FINAL;
- }
- pIHtmlElement = NULL;
- ASSERT(FALSE);
- goto FINAL;
- }
- hr = pIHtmlElement->QueryInterface(IID_IHTMLElement2, (VOID**)&pIHtmlElement2);
- if (FAILED(hr))
- {
- pIHtmlElement2 = NULL;
- ASSERT(FALSE);
- goto FINAL;
- }
- hr = pIHtmlDocument2->createElement(bstrElementType, &pIHtmlElementScript);
- if (FAILED(hr))
- {
- pIHtmlElementScript = NULL;
- ASSERT(FALSE);
- goto FINAL;
- }
- hr = pIHtmlElementScript->QueryInterface(IID_IHTMLScriptElement, (VOID**)&pIHtmlScript);
- if (FAILED(hr))
- {
- pIHtmlScript = NULL;
- ASSERT(FALSE);
- goto FINAL;
- }
- hr = pIHtmlScript->put_defer(VARIANT_TRUE);
- if (FAILED(hr))
- {
- ASSERT(FALSE);
- goto FINAL;
- }
- hr = pIHtmlScript->put_text(bstrScript);
- if (FAILED(hr))
- {
- ASSERT(FALSE);
- goto FINAL;
- }
- hr = pIHtmlElement2->insertAdjacentElement(bstrInsertWhere, pIHtmlElementScript, NULL);
- if (FAILED(hr))
- {
- ASSERT(FALSE);
- goto FINAL;
- }
- // 여기까지 왔다면, 일단 성공~
- hr = S_OK;
- hr2 = pIHtmlDocument2->get_frames(&pIHtmlFramesCollection);
- if (FAILED(hr2))
- {
- // Frame이 없는 깔끔한 경우이다~
- goto FINAL;
- }
- hr2 = pIHtmlFramesCollection->get_length(&nFrameCount);
- if (FAILED(hr2))
- {
- goto FINAL;
- }
- for (i=0; i<nframecount; vardispwin.pdispval-="" {="" !="varDispWin.pdispVal)" (null="" if="" vardispwin.pdispval="NULL;" vardispwin.vt="VT_DISPATCH;" varindex.lval="i;" varindex.vt="VT_I4;" i++)="">Release();
- varDispWin.pdispVal = NULL;
- }
- hr2 = pIHtmlFramesCollection->item(&varIndex, &varDispWin);
- if (FAILED(hr2))
- {
- continue;
- }
- if (NULL == varDispWin.pdispVal)
- {
- ASSERT(FALSE);
- continue;
- }
- if (NULL != pIHtmlWindow)
- {
- pIHtmlWindow->Release();
- pIHtmlWindow = NULL;
- }
- hr2 = varDispWin.pdispVal->QueryInterface(IID_IHTMLWindow2, (VOID**)&pIHtmlWindow);
- if (FAILED(hr2))
- {
- continue;
- }
- if (NULL == pIHtmlWindow)
- {
- ASSERT(FALSE);
- continue;
- }
- if (NULL != pIHtmlDocument2Frame)
- {
- pIHtmlDocument2Frame->Release();
- pIHtmlDocument2Frame = NULL;
- }
- hr2 = pIHtmlWindow->get_document(&pIHtmlDocument2Frame);
- if (FAILED(hr2))
- {
- continue;
- }
- if (NULL == pIHtmlDocument2Frame)
- {
- ASSERT(FALSE);
- continue;
- }
- // Recursive 실행~!!!
- hr2 = InjectJScriptByDocumentRecurse(pIHtmlDocument2Frame, lpszJScript, nMaxRecurseFrame, nCurDepth+1, pbStackOverflow);
- // StackOverflow
- if (HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW) == hr2)
- {
- (*pbStackOverflow) = TRUE;
- hr = HRESULT_FROM_WIN32(ERROR_STACK_OVERFLOW);
- break;
- }
- }
- FINAL:
- if (NULL != pIHtmlDocument2Frame)
- {
- pIHtmlDocument2Frame->Release();
- pIHtmlDocument2Frame = NULL;
- }
- if (NULL != pIHtmlWindow)
- {
- pIHtmlWindow->Release();
- pIHtmlWindow = NULL;
- }
- if (NULL != varDispWin.pdispVal)
- {
- varDispWin.pdispVal->Release();
- varDispWin.pdispVal = NULL;
- }
- if (NULL != pIHtmlScript)
- {
- pIHtmlScript->Release();
- pIHtmlScript = NULL;
- }
- if (NULL != pIHtmlElementScript)
- {
- pIHtmlElementScript->Release();
- pIHtmlElementScript = NULL;
- }
- if (NULL != pIHtmlElement2)
- {
- pIHtmlElement2->Release();
- pIHtmlElement2 = NULL;
- }
- if (NULL != pIHtmlElement)
- {
- pIHtmlElement->Release();
- pIHtmlElement = NULL;
- }
- ::SysFreeString(bstrScript);
- ::SysFreeString(bstrElementType);
- ::SysFreeString(bstrInsertWhere);
- return hr;
- }
- </nframecount;>
'프로그래밍 > Let's Share it' 카테고리의 다른 글
ini 파일을 암호화하여 읽고 쓰기 (0) | 2010.12.26 |
---|---|
어떤 계정에서도 읽고 쓸수 있는 경로 구하기 (0) | 2010.12.10 |
CHtmlView의 C++에서 생성한 JScript를 Inject하여 실행하기 (0) | 2010.11.03 |
CBitmapButton의 투명(Transparent)와 Hover 지원하기 (22) | 2010.11.01 |
Crash 발생시 스스로 미니 덤프를 생성하는 코드 공유와 간략한 덤프 분석 방법 (1) | 2009.09.25 |