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; i++) {
varIndex.vt = VT_I4;
varIndex.lVal = i;
if (NULL != varDispWin.pdispVal) {
varDispWin.pdispVal -> 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;
}