2010. 12. 8. 16:59
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; iRelease(); 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; }
'프로그래밍 > 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 |