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.
1275 lines
48 KiB
1275 lines
48 KiB
//*********************************************************************
|
|
//* Microsoft Windows **
|
|
//* Copyright(c) Microsoft Corp., 1994 **
|
|
//*********************************************************************
|
|
|
|
//
|
|
// WALKER.CPP - Functions for walking an HTML input file
|
|
//
|
|
|
|
// HISTORY:
|
|
//
|
|
// 05/13/98 donaldm Created.
|
|
//
|
|
//*********************************************************************
|
|
|
|
#include "pre.h"
|
|
#include <urlmon.h>
|
|
#include <mshtmdid.h>
|
|
#include <mshtml.h>
|
|
#include <shlobj.h>
|
|
|
|
const TCHAR cszEquals[] = TEXT("=");
|
|
const TCHAR cszAmpersand[] = TEXT("&");
|
|
const TCHAR cszPlus[] = TEXT("+");
|
|
const TCHAR cszQuestion[] = TEXT("?");
|
|
const TCHAR cszFormNamePAGEID[] = TEXT("PAGEID");
|
|
const TCHAR cszFormNameBACK[] = TEXT("BACK");
|
|
const TCHAR cszFormNamePAGETYPE[] = TEXT("PAGETYPE");
|
|
const TCHAR cszFormNameNEXT[] = TEXT("NEXT");
|
|
const TCHAR cszFormNamePAGEFLAG[] = TEXT("PAGEFLAG");
|
|
const TCHAR cszPageTypeTERMS[] = TEXT("TERMS");
|
|
const TCHAR cszPageTypeCUSTOMFINISH[] = TEXT("CUSTOMFINISH");
|
|
const TCHAR cszPageTypeFINISH[] = TEXT("FINISH");
|
|
const TCHAR cszPageTypeNORMAL[] = TEXT("");
|
|
const TCHAR cszOLSRegEntries[] = TEXT("regEntries");
|
|
const TCHAR cszKeyName[] = TEXT("KeyName");
|
|
const TCHAR cszEntryName[] = TEXT("EntryName");
|
|
const TCHAR cszEntryValue[] = TEXT("EntryValue");
|
|
const TCHAR cszOLSDesktopShortcut[] = TEXT("DesktopShortcut");
|
|
const TCHAR cszSourceName[] = TEXT("SourceName");
|
|
const TCHAR cszTargetName[] = TEXT("TargetName");
|
|
|
|
#define HARDCODED_IEAK_ISPFILE_ELEMENT_ID TEXT("g_IspFilePath")
|
|
|
|
// COM interfaces
|
|
STDMETHODIMP CWalker::QueryInterface(REFIID riid, LPVOID* ppv)
|
|
{
|
|
*ppv = NULL;
|
|
|
|
if (IID_IUnknown == riid || IID_IPropertyNotifySink == riid)
|
|
{
|
|
*ppv = (LPUNKNOWN)(IPropertyNotifySink*)this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
else if (IID_IOleClientSite == riid)
|
|
{
|
|
*ppv = (IOleClientSite*)this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
else if (IID_IDispatch == riid)
|
|
{
|
|
*ppv = (IDispatch*)this;
|
|
AddRef();
|
|
return NOERROR;
|
|
}
|
|
else
|
|
{
|
|
return E_NOTIMPL;
|
|
}
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CWalker::AddRef()
|
|
{
|
|
return ++m_cRef;
|
|
}
|
|
|
|
STDMETHODIMP_(ULONG) CWalker::Release()
|
|
{
|
|
if (!(--m_cRef))
|
|
{
|
|
delete this;
|
|
}
|
|
return m_cRef;
|
|
}
|
|
|
|
// Fired on change of the value of a 'bindable' property
|
|
STDMETHODIMP CWalker::OnChanged(DISPID dispID)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (DISPID_READYSTATE == dispID)
|
|
{
|
|
// check the value of the readystate property
|
|
assert(m_pMSHTML);
|
|
|
|
VARIANT vResult = {0};
|
|
EXCEPINFO excepInfo;
|
|
UINT uArgErr;
|
|
|
|
DISPPARAMS dp = {NULL, NULL, 0, 0};
|
|
if (SUCCEEDED(hr = m_pMSHTML->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
|
|
DISPATCH_PROPERTYGET, &dp, &vResult, &excepInfo, &uArgErr)))
|
|
{
|
|
assert(VT_I4 == V_VT(&vResult));
|
|
if (READYSTATE_COMPLETE == (READYSTATE)V_I4(&vResult))
|
|
SetEvent(m_hEventTridentDone);
|
|
VariantClear(&vResult);
|
|
}
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
// MSHTML Queries for the IDispatch interface of the host through the IOleClientSite
|
|
// interface that MSHTML is passed through its implementation of IOleObject::SetClientSite()
|
|
STDMETHODIMP CWalker::Invoke(DISPID dispIdMember,
|
|
REFIID riid,
|
|
LCID lcid,
|
|
WORD wFlags,
|
|
DISPPARAMS __RPC_FAR *pDispParams,
|
|
VARIANT __RPC_FAR *pVarResult,
|
|
EXCEPINFO __RPC_FAR *pExcepInfo,
|
|
UINT __RPC_FAR *puArgErr)
|
|
{
|
|
if (!pVarResult)
|
|
{
|
|
return E_POINTER;
|
|
}
|
|
|
|
switch(dispIdMember)
|
|
{
|
|
case DISPID_AMBIENT_DLCONTROL:
|
|
// respond to this ambient to indicate that we only want to
|
|
// download the page, but we don't want to run scripts,
|
|
// Java applets, or ActiveX controls
|
|
V_VT(pVarResult) = VT_I4;
|
|
V_I4(pVarResult) = DLCTL_DOWNLOADONLY |
|
|
DLCTL_NO_SCRIPTS |
|
|
DLCTL_NO_JAVA |
|
|
DLCTL_NO_DLACTIVEXCTLS |
|
|
DLCTL_NO_RUNACTIVEXCTLS;
|
|
break;
|
|
|
|
default:
|
|
return DISP_E_MEMBERNOTFOUND;
|
|
}
|
|
return NOERROR;
|
|
}
|
|
|
|
// A more traditional form of persistence.
|
|
// MSHTML performs this asynchronously as well.
|
|
HRESULT CWalker::LoadURLFromFile(BSTR bstrURL)
|
|
{
|
|
HRESULT hr;
|
|
|
|
LPPERSISTFILE pPF;
|
|
// MSHTML supports file persistence for ordinary files.
|
|
if ( SUCCEEDED(hr = m_pMSHTML->QueryInterface(IID_IPersistFile, (LPVOID*) &pPF)))
|
|
{
|
|
hr = pPF->Load(bstrURL, 0);
|
|
pPF->Release();
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
// Local interfaces
|
|
|
|
// This function will attached trient to a location FILE: URL, and ensure that it is ready
|
|
// to be walked
|
|
HRESULT CWalker::InitForMSHTML()
|
|
{
|
|
HRESULT hr;
|
|
LPCONNECTIONPOINTCONTAINER pCPC = NULL;
|
|
LPOLEOBJECT pOleObject = NULL;
|
|
LPOLECONTROL pOleControl = NULL;
|
|
|
|
// Create an instance of an dynamic HTML document
|
|
if (FAILED(hr = CoCreateInstance( CLSID_HTMLDocument, NULL,
|
|
CLSCTX_INPROC_SERVER, IID_IHTMLDocument2,
|
|
(LPVOID*)&m_pTrident )))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
|
|
if (FAILED(hr = m_pTrident->QueryInterface(IID_IOleObject, (LPVOID*)&pOleObject)))
|
|
{
|
|
goto Error;
|
|
}
|
|
hr = pOleObject->SetClientSite((IOleClientSite*)this);
|
|
pOleObject->Release();
|
|
|
|
if (FAILED(hr = m_pTrident->QueryInterface(IID_IOleControl, (LPVOID*)&pOleControl)))
|
|
{
|
|
goto Error;
|
|
}
|
|
hr = pOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
|
|
pOleControl->Release();
|
|
|
|
// Hook up sink to catch ready state property change
|
|
if (FAILED(hr = m_pTrident->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC)))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
if (FAILED(hr = pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &m_pCP)))
|
|
{
|
|
goto Error;
|
|
}
|
|
|
|
m_hrConnected = m_pCP->Advise((LPUNKNOWN)(IPropertyNotifySink*)this, &m_dwCookie);
|
|
|
|
Error:
|
|
if (pCPC)
|
|
pCPC->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
// Clean up connection point
|
|
HRESULT CWalker::TermForMSHTML()
|
|
{
|
|
HRESULT hr = NOERROR;
|
|
|
|
// Disconnect from property change notifications
|
|
if (SUCCEEDED(m_hrConnected))
|
|
{
|
|
hr = m_pCP->Unadvise(m_dwCookie);
|
|
}
|
|
|
|
// Release the connection point
|
|
if (m_pCP)
|
|
m_pCP->Release();
|
|
|
|
if (m_pTrident)
|
|
m_pTrident->Release();
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWalker::ExtractUnHiddenText(BSTR* pbstrText)
|
|
{
|
|
VARIANT vIndex;
|
|
LPDISPATCH pDisp;
|
|
IHTMLInputHiddenElement* pHidden;
|
|
IHTMLElement* pElement;
|
|
BSTR bstrValue;
|
|
VARIANT var2 = { 0 };
|
|
long lLen = 0;
|
|
|
|
vIndex.vt = VT_UINT;
|
|
bstrValue = SysAllocString(A2W(TEXT("\0")));
|
|
|
|
|
|
Walk();
|
|
|
|
if (!m_pNextForm)
|
|
return E_UNEXPECTED;
|
|
|
|
m_pNextForm->get_length(&lLen);
|
|
|
|
for (int i = 0; i < lLen; i++)
|
|
{
|
|
vIndex.lVal = i;
|
|
pDisp = NULL;
|
|
|
|
if(SUCCEEDED(m_pNextForm->item(vIndex, var2, &pDisp)) && pDisp)
|
|
{
|
|
pHidden = NULL;
|
|
|
|
if(SUCCEEDED(pDisp->QueryInterface(IID_IHTMLInputHiddenElement, (LPVOID*)&pHidden)) && pHidden)
|
|
{
|
|
pHidden->put_value(bstrValue);
|
|
pHidden->Release();
|
|
}
|
|
pDisp->Release();
|
|
}
|
|
}
|
|
|
|
if (SUCCEEDED(m_pNextForm->QueryInterface(IID_IHTMLElement, (LPVOID*)&pElement)) && pElement)
|
|
pElement->get_innerHTML(pbstrText);
|
|
|
|
SysFreeString(bstrValue);
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CWalker::AttachToMSHTML(BSTR bstrURL)
|
|
{
|
|
HRESULT hr;
|
|
|
|
// Release any previous instance of the HTML document pointer we might be holding on to
|
|
if(m_pMSHTML)
|
|
{
|
|
m_pMSHTML->Release();
|
|
m_pMSHTML = NULL;
|
|
}
|
|
|
|
m_pMSHTML = m_pTrident;
|
|
m_pMSHTML->AddRef();
|
|
|
|
m_hEventTridentDone = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
|
hr = LoadURLFromFile(bstrURL);
|
|
if (SUCCEEDED(hr) || (E_PENDING == hr))
|
|
{
|
|
if (m_hEventTridentDone)
|
|
{
|
|
MSG msg;
|
|
DWORD dwRetCode;
|
|
HANDLE hEventList[1];
|
|
hEventList[0] = m_hEventTridentDone;
|
|
|
|
while (TRUE)
|
|
{
|
|
// We will wait on window messages and also the named event.
|
|
dwRetCode = MsgWaitForMultipleObjects(1,
|
|
&hEventList[0],
|
|
FALSE,
|
|
300000, // 5 minutes
|
|
QS_ALLINPUT);
|
|
|
|
// Determine why we came out of MsgWaitForMultipleObjects(). If
|
|
// we timed out then let's do some TrialWatcher work. Otherwise
|
|
// process the message that woke us up.
|
|
if (WAIT_TIMEOUT == dwRetCode)
|
|
{
|
|
break;
|
|
}
|
|
else if (WAIT_OBJECT_0 == dwRetCode)
|
|
{
|
|
break;
|
|
}
|
|
else if (WAIT_OBJECT_0 + 1 == dwRetCode)
|
|
{
|
|
// Process all messages in the Queue, since MsgWaitForMultipleObjects
|
|
// will not do this for us
|
|
while (TRUE)
|
|
{
|
|
if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
|
|
{
|
|
if (WM_QUIT == msg.message)
|
|
{
|
|
break;
|
|
}
|
|
else
|
|
{
|
|
TranslateMessage(&msg);
|
|
DispatchMessage(&msg);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
CloseHandle(m_hEventTridentDone);
|
|
m_hEventTridentDone = 0;
|
|
}
|
|
else
|
|
{
|
|
// If we were pending, and we could not wait, we got a problem...
|
|
if(E_PENDING == hr)
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT CWalker::AttachToDocument(IWebBrowser2 *lpWebBrowser)
|
|
{
|
|
HRESULT hr;
|
|
LPDISPATCH pDisp;
|
|
|
|
// Release any previous instance of the HTML document pointer we might be holding on to
|
|
if(m_pMSHTML)
|
|
{
|
|
// If the m_pMSHMTL is NOT our internal Trident object (for walking files)
|
|
// then sombody did not do a detach, so we need to release the previous
|
|
// MSHTML object
|
|
if (m_pMSHTML != m_pTrident)
|
|
m_pMSHTML->Release();
|
|
m_pMSHTML = NULL;
|
|
}
|
|
|
|
// Make sure we have a webbrowser to grab onto
|
|
ASSERT(lpWebBrowser);
|
|
|
|
// Get the document pointer from this webbrowser.
|
|
if (SUCCEEDED(hr = lpWebBrowser->get_Document(&pDisp)))
|
|
{
|
|
if (pDisp)
|
|
{
|
|
hr = pDisp->QueryInterface( IID_IHTMLDocument2, (LPVOID*)&m_pMSHTML );
|
|
// Paranoia, but trident/shdocvw might say OK, but really not give us a document
|
|
if (!m_pMSHTML)
|
|
hr = E_FAIL;
|
|
|
|
pDisp->Release();
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
}
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT CWalker::Detach()
|
|
{
|
|
if (m_pPageIDForm)
|
|
{
|
|
m_pPageIDForm->Release();
|
|
m_pPageIDForm = NULL;
|
|
}
|
|
if (m_pBackForm)
|
|
{
|
|
m_pBackForm->Release();
|
|
m_pBackForm = NULL;
|
|
}
|
|
if (m_pPageTypeForm)
|
|
{
|
|
m_pPageTypeForm->Release();
|
|
m_pPageTypeForm = NULL;
|
|
}
|
|
if (m_pNextForm)
|
|
{
|
|
m_pNextForm->Release();
|
|
m_pNextForm = NULL;
|
|
}
|
|
if (m_pPageFlagForm)
|
|
{
|
|
m_pPageFlagForm->Release();
|
|
m_pPageFlagForm = NULL;
|
|
}
|
|
if(m_pMSHTML)
|
|
{
|
|
// If the m_pMSHMTL is NOT our internal Trident object (for walking files)
|
|
// then sombody did not do a detach, so we need to release the previous
|
|
// MSHTML object
|
|
if (m_pMSHTML != m_pTrident)
|
|
m_pMSHTML->Release();
|
|
m_pMSHTML = NULL;
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
// Walk the object model.
|
|
HRESULT CWalker::Walk()
|
|
{
|
|
HRESULT hr;
|
|
IHTMLElementCollection* pColl = NULL;
|
|
|
|
assert(m_pMSHTML);
|
|
if (!m_pMSHTML)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
// retrieve a reference to the ALL collection
|
|
if (SUCCEEDED(hr = m_pMSHTML->get_all( &pColl )))
|
|
{
|
|
long cElems;
|
|
|
|
assert(pColl);
|
|
|
|
// retrieve the count of elements in the collection
|
|
if (SUCCEEDED(hr = pColl->get_length( &cElems )))
|
|
{
|
|
// for each element retrieve properties such as TAGNAME and HREF
|
|
for ( int i=0; i<cElems; i++ )
|
|
{
|
|
VARIANT vIndex;
|
|
vIndex.vt = VT_UINT;
|
|
vIndex.lVal = i;
|
|
VARIANT var2 = { 0 };
|
|
LPDISPATCH pDisp;
|
|
|
|
if (SUCCEEDED(hr = pColl->item( vIndex, var2, &pDisp )))
|
|
{
|
|
// Look for <FORM> tags
|
|
IHTMLFormElement* pForm = NULL;
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLFormElement, (LPVOID*)&pForm )))
|
|
{
|
|
BSTR bstrName;
|
|
|
|
assert(pForm);
|
|
|
|
// Get the Name
|
|
hr = pForm->get_name(&bstrName);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPTSTR lpszName = W2A(bstrName);
|
|
|
|
// See what kind it is
|
|
if (lstrcmpi(lpszName, cszFormNamePAGEID) == 0)
|
|
{
|
|
m_pPageIDForm = pForm;
|
|
m_pPageIDForm->AddRef();
|
|
}
|
|
else if (lstrcmpi(lpszName, cszFormNameBACK) == 0)
|
|
{
|
|
m_pBackForm = pForm;
|
|
m_pBackForm->AddRef();
|
|
}
|
|
else if (lstrcmpi(lpszName, cszFormNamePAGETYPE) == 0)
|
|
{
|
|
m_pPageTypeForm = pForm;
|
|
m_pPageTypeForm->AddRef();
|
|
}
|
|
else if (lstrcmpi(lpszName, cszFormNameNEXT) == 0)
|
|
{
|
|
m_pNextForm = pForm;
|
|
m_pNextForm->AddRef();
|
|
}
|
|
else if (lstrcmpi(lpszName, cszFormNamePAGEFLAG) == 0)
|
|
{
|
|
m_pPageFlagForm = pForm;
|
|
m_pPageFlagForm->AddRef();
|
|
}
|
|
|
|
SysFreeString(bstrName);
|
|
}
|
|
pForm->Release();
|
|
}
|
|
pDisp->Release();
|
|
} // item
|
|
} // for
|
|
} // get_length
|
|
pColl->Release();
|
|
} // get_all
|
|
|
|
return hr;
|
|
}
|
|
|
|
|
|
|
|
HRESULT CWalker::get_IsQuickFinish(BOOL* pbIsQuickFinish)
|
|
{
|
|
if (!m_pPageTypeForm)
|
|
return (E_FAIL);
|
|
|
|
IHTMLElement* pElement = NULL;
|
|
VARIANT varValue;
|
|
VariantInit(&varValue);
|
|
|
|
V_VT(&varValue) = VT_BSTR;
|
|
*pbIsQuickFinish = FALSE;
|
|
|
|
if (SUCCEEDED(m_pPageTypeForm->QueryInterface(IID_IHTMLElement, (void**)&pElement)))
|
|
{
|
|
if (SUCCEEDED(pElement->getAttribute(A2W(TEXT("QUICKFINISH")), FALSE, &varValue)))
|
|
{
|
|
if (VT_NULL != varValue.vt)
|
|
{
|
|
if(lstrcmpi(W2A(varValue.bstrVal), TEXT("TRUE")) == 0)
|
|
*pbIsQuickFinish = TRUE;
|
|
}
|
|
}
|
|
pElement->Release();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CWalker::get_PageType(LPDWORD pdwPageType)
|
|
{
|
|
BSTR bstr;
|
|
HRESULT hr;
|
|
|
|
if (!m_pPageTypeForm)
|
|
return (E_FAIL);
|
|
|
|
// Get the Action for the PageType Form
|
|
hr = m_pPageTypeForm->get_action(&bstr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPTSTR lpszType = W2A(bstr);
|
|
|
|
// See what kind it is
|
|
if (lstrcmpi(lpszType, cszPageTypeTERMS) == 0)
|
|
*pdwPageType = PAGETYPE_ISP_TOS;
|
|
else if (lstrcmpi(lpszType, cszPageTypeCUSTOMFINISH) == 0)
|
|
*pdwPageType = PAGETYPE_ISP_CUSTOMFINISH;
|
|
else if (lstrcmpi(lpszType, cszPageTypeFINISH) == 0)
|
|
*pdwPageType = PAGETYPE_ISP_FINISH;
|
|
else if (lstrcmpi(lpszType, cszPageTypeNORMAL) == 0)
|
|
*pdwPageType = PAGETYPE_ISP_NORMAL;
|
|
else
|
|
*pdwPageType = PAGETYPE_UNDEFINED;
|
|
|
|
SysFreeString(bstr);
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT CWalker::get_PageFlag(LPDWORD pdwPageFlag)
|
|
{
|
|
BSTR bstr;
|
|
HRESULT hr;
|
|
|
|
*pdwPageFlag = 0;
|
|
|
|
if (!m_pPageFlagForm)
|
|
return (E_FAIL);
|
|
|
|
// Get the Action for the PageFlag Form
|
|
hr = m_pPageFlagForm->get_action(&bstr);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
LPTSTR lpszType = W2A(bstr);
|
|
|
|
// See what kind it is
|
|
*pdwPageFlag = _ttol(lpszType);
|
|
|
|
SysFreeString(bstr);
|
|
}
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT CWalker::get_PageID(BSTR *pbstrPageID)
|
|
{
|
|
HRESULT hr;
|
|
|
|
if (!m_pPageIDForm)
|
|
return (E_FAIL);
|
|
|
|
if (!pbstrPageID)
|
|
return (E_FAIL);
|
|
|
|
// Get the Action for the PageType Form
|
|
hr = m_pPageIDForm->get_action(pbstrPageID);
|
|
|
|
return (hr);
|
|
}
|
|
|
|
HRESULT CWalker::getQueryString
|
|
(
|
|
IHTMLFormElement *pForm,
|
|
LPTSTR lpszQuery
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
long lFormLength;
|
|
|
|
if (SUCCEEDED(pForm->get_length(&lFormLength)))
|
|
{
|
|
for (int i = 0; i < lFormLength; i++)
|
|
{
|
|
VARIANT vIndex;
|
|
vIndex.vt = VT_UINT;
|
|
vIndex.lVal = i;
|
|
VARIANT var2 = { 0 };
|
|
LPDISPATCH pDisp;
|
|
|
|
if (SUCCEEDED(hr = pForm->item( vIndex, var2, &pDisp )))
|
|
{
|
|
// See if the Item is a Input button
|
|
IHTMLButtonElement* pButton = NULL;
|
|
IHTMLInputButtonElement* pInputButton = NULL;
|
|
IHTMLInputFileElement* pInputFile = NULL;
|
|
IHTMLInputHiddenElement* pInputHidden = NULL;
|
|
IHTMLInputTextElement* pInputText = NULL;
|
|
IHTMLSelectElement* pSelect = NULL;
|
|
IHTMLTextAreaElement* pTextArea = NULL;
|
|
IHTMLOptionButtonElement* pOptionButton = NULL;
|
|
|
|
// First check to see if this is an OptionButton.
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLOptionButtonElement, (LPVOID*)&pOptionButton )))
|
|
{
|
|
BSTR bstr = NULL;
|
|
|
|
// See if it is a Radio or a CheckBox
|
|
if (SUCCEEDED(pOptionButton->get_type(&bstr)))
|
|
{
|
|
LPTSTR lpszType = W2A(bstr);
|
|
|
|
if ((lstrcmpi(lpszType, TEXT("radio")) == 0) || (lstrcmpi(lpszType, TEXT("checkbox")) == 0))
|
|
{
|
|
short bChecked;
|
|
// See if the button is checked. If it is, then it needs to be
|
|
// added to the query string
|
|
if (SUCCEEDED(pOptionButton->get_checked(&bChecked)))
|
|
{
|
|
if(bChecked)
|
|
{
|
|
BSTR bstrName;
|
|
BSTR bstrValue;
|
|
|
|
|
|
if ( SUCCEEDED(pOptionButton->get_name(&bstrName)) &&
|
|
SUCCEEDED(pOptionButton->get_value(&bstrValue)) )
|
|
{
|
|
if (bstrValue)
|
|
{
|
|
size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
|
|
TCHAR* szVal = (TCHAR*)malloc(size * 3);
|
|
if (szVal)
|
|
{
|
|
memcpy(szVal, W2A(bstrValue), size);
|
|
URLEncode(szVal, size * 3);
|
|
URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
|
|
// Cleanup
|
|
free(szVal);
|
|
}
|
|
SysFreeString(bstrName);
|
|
SysFreeString(bstrValue);
|
|
}
|
|
}
|
|
|
|
}
|
|
}
|
|
}
|
|
SysFreeString(bstr);
|
|
|
|
}
|
|
|
|
// Release the interface
|
|
pOptionButton->Release();
|
|
continue;
|
|
}
|
|
|
|
// For the rest we need to form Name=Value pairs
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLButtonElement, (LPVOID*)&pButton )))
|
|
{
|
|
BSTR bstrName;
|
|
BSTR bstrValue;
|
|
|
|
if (SUCCEEDED(pButton->get_name(&bstrName)) &&
|
|
SUCCEEDED(pButton->get_value(&bstrValue)) )
|
|
{
|
|
if (bstrValue)
|
|
{
|
|
size_t size = sizeof(TCHAR) * (lstrlen(W2A(bstrValue)) + 1 );
|
|
TCHAR* szVal = (TCHAR*)malloc(size * 3);
|
|
if (szVal)
|
|
{
|
|
memcpy(szVal, W2A(bstrValue), size);
|
|
URLEncode(szVal, size * 3);
|
|
URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
|
|
// Cleanup
|
|
free(szVal);
|
|
}
|
|
SysFreeString(bstrName);
|
|
SysFreeString(bstrValue);
|
|
}
|
|
}
|
|
|
|
// Release the interface pointer
|
|
pButton->Release();
|
|
continue;
|
|
}
|
|
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLInputFileElement, (LPVOID*)&pInputFile )))
|
|
{
|
|
BSTR bstrName;
|
|
BSTR bstrValue;
|
|
|
|
if (SUCCEEDED(pInputFile->get_name(&bstrName)) &&
|
|
SUCCEEDED(pInputFile->get_value(&bstrValue)) )
|
|
{
|
|
if (bstrValue)
|
|
{
|
|
size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
|
|
TCHAR* szVal = (TCHAR*)malloc(size * 3);
|
|
if (szVal)
|
|
{
|
|
memcpy(szVal, W2A(bstrValue), size);
|
|
URLEncode(szVal, size * 3);
|
|
URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
|
|
// Cleanup
|
|
free(szVal);
|
|
}
|
|
SysFreeString(bstrName);
|
|
SysFreeString(bstrValue);
|
|
}
|
|
}
|
|
|
|
// Release the interface pointer
|
|
pInputFile->Release();
|
|
continue;
|
|
}
|
|
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLInputHiddenElement, (LPVOID*)&pInputHidden )))
|
|
{
|
|
BSTR bstrName;
|
|
BSTR bstrValue;
|
|
|
|
if (SUCCEEDED(pInputHidden->get_name(&bstrName)) &&
|
|
SUCCEEDED(pInputHidden->get_value(&bstrValue)) )
|
|
{
|
|
if (bstrValue)
|
|
{
|
|
size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
|
|
TCHAR* szVal = (TCHAR*)malloc(size * 3);
|
|
if (szVal)
|
|
{
|
|
memcpy(szVal, W2A(bstrValue), size);
|
|
URLEncode(szVal, size * 3);
|
|
URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
|
|
// Cleanup
|
|
free(szVal);
|
|
}
|
|
SysFreeString(bstrName);
|
|
SysFreeString(bstrValue);
|
|
}
|
|
}
|
|
|
|
// Release the interface pointer
|
|
pInputHidden->Release();
|
|
continue;
|
|
}
|
|
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLInputTextElement, (LPVOID*)&pInputText )))
|
|
{
|
|
BSTR bstrName;
|
|
BSTR bstrValue;
|
|
|
|
if (SUCCEEDED(pInputText->get_name(&bstrName)) &&
|
|
SUCCEEDED(pInputText->get_value(&bstrValue)) )
|
|
{
|
|
if (bstrValue)
|
|
{
|
|
size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
|
|
TCHAR* szVal = (TCHAR*)malloc(size * 3);
|
|
if (szVal)
|
|
{
|
|
memcpy(szVal, W2A(bstrValue), size);
|
|
URLEncode(szVal, size * 3);
|
|
URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
|
|
// Cleanup
|
|
free(szVal);
|
|
}
|
|
SysFreeString(bstrName);
|
|
SysFreeString(bstrValue);
|
|
}
|
|
}
|
|
|
|
// Release the interface pointer
|
|
pInputText->Release();
|
|
continue;
|
|
}
|
|
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLSelectElement, (LPVOID*)&pSelect )))
|
|
{
|
|
BSTR bstrName;
|
|
BSTR bstrValue;
|
|
|
|
if (SUCCEEDED(pSelect->get_name(&bstrName)) &&
|
|
SUCCEEDED(pSelect->get_value(&bstrValue)) )
|
|
{
|
|
if (bstrValue)
|
|
{
|
|
size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
|
|
TCHAR* szVal = (TCHAR*)malloc(size * 3);
|
|
if (szVal)
|
|
{
|
|
memcpy(szVal, W2A(bstrValue), size);
|
|
URLEncode(szVal, size * 3);
|
|
URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
|
|
// Cleanup
|
|
free(szVal);
|
|
}
|
|
SysFreeString(bstrName);
|
|
SysFreeString(bstrValue);
|
|
}
|
|
}
|
|
|
|
// Release the interface pointer
|
|
pSelect->Release();
|
|
continue;
|
|
}
|
|
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLTextAreaElement, (LPVOID*)&pTextArea )))
|
|
{
|
|
BSTR bstrName;
|
|
BSTR bstrValue;
|
|
|
|
if (SUCCEEDED(pTextArea->get_name(&bstrName)) &&
|
|
SUCCEEDED(pTextArea->get_value(&bstrValue)) )
|
|
{
|
|
if (bstrValue)
|
|
{
|
|
size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
|
|
TCHAR* szVal = (TCHAR*)malloc(size * 3);
|
|
if (szVal)
|
|
{
|
|
memcpy(szVal, W2A(bstrValue), size);
|
|
URLEncode(szVal, size * 3);
|
|
URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
|
|
// Cleanup
|
|
free(szVal);
|
|
}
|
|
SysFreeString(bstrName);
|
|
SysFreeString(bstrValue);
|
|
}
|
|
}
|
|
|
|
// Release the interface pointer
|
|
pTextArea->Release();
|
|
}
|
|
pDisp->Release();
|
|
}
|
|
}
|
|
}
|
|
|
|
// Null out the last Ampersand, since we don't know when we added the last pair, so we got
|
|
// a trailing ampersand
|
|
lpszQuery[lstrlen(lpszQuery)-1] = '\0';
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT CWalker::get_FirstFormQueryString
|
|
(
|
|
LPTSTR lpszQuery
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
IHTMLElementCollection *pColl = NULL;
|
|
BOOL bDone = FALSE;
|
|
|
|
assert(m_pMSHTML);
|
|
if (!m_pMSHTML)
|
|
{
|
|
return E_UNEXPECTED;
|
|
}
|
|
|
|
// retrieve a reference to the ALL collection
|
|
if (SUCCEEDED(hr = m_pMSHTML->get_all( &pColl )))
|
|
{
|
|
long cElems;
|
|
|
|
assert(pColl);
|
|
|
|
// retrieve the count of elements in the collection
|
|
if (SUCCEEDED(hr = pColl->get_length( &cElems )))
|
|
{
|
|
// for each element retrieve properties such as TAGNAME and HREF
|
|
for ( int i=0; (i<cElems) && !bDone; i++ )
|
|
{
|
|
VARIANT vIndex;
|
|
vIndex.vt = VT_UINT;
|
|
vIndex.lVal = i;
|
|
VARIANT var2 = { 0 };
|
|
LPDISPATCH pDisp;
|
|
|
|
if (SUCCEEDED(hr = pColl->item( vIndex, var2, &pDisp )))
|
|
{
|
|
// Look for <FORM> tags
|
|
IHTMLFormElement* pForm = NULL;
|
|
if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLFormElement, (LPVOID*)&pForm )))
|
|
{
|
|
assert(pForm);
|
|
|
|
if (SUCCEEDED(getQueryString(pForm, lpszQuery)))
|
|
{
|
|
hr = ERROR_SUCCESS;
|
|
}
|
|
else
|
|
{
|
|
hr = E_FAIL;
|
|
}
|
|
|
|
pForm->Release();
|
|
bDone = TRUE;
|
|
}
|
|
pDisp->Release();
|
|
}
|
|
}
|
|
}
|
|
pColl->Release();
|
|
}
|
|
|
|
// If we fall out of the loop, that is bad, so return a failure code
|
|
if (!bDone)
|
|
hr = E_FAIL;
|
|
|
|
return (hr);
|
|
}
|
|
|
|
// For the URL for the next page
|
|
HRESULT CWalker::get_URL
|
|
(
|
|
LPTSTR lpszURL,
|
|
BOOL bForward
|
|
)
|
|
{
|
|
|
|
HRESULT hr = S_OK;
|
|
BSTR bstrURL;
|
|
TCHAR szQuery[INTERNET_MAX_URL_LENGTH];
|
|
IHTMLFormElement * pForm = bForward ? get_pNextForm() : get_pBackForm();
|
|
|
|
if (!pForm)
|
|
return (E_FAIL);
|
|
|
|
|
|
// Get the Action for the Next Form
|
|
hr = pForm->get_action(&bstrURL);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
memset(szQuery, 0, sizeof(szQuery));
|
|
lstrcpy(szQuery, cszQuestion);
|
|
|
|
// Get the Query String
|
|
if (SUCCEEDED(getQueryString(pForm, szQuery)))
|
|
{
|
|
// Catenate the two together into the dest buffer
|
|
lstrcpy(lpszURL, W2A(bstrURL));
|
|
lstrcat(lpszURL, szQuery);
|
|
}
|
|
|
|
SysFreeString(bstrURL);
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT CWalker::get_IeakIspFile(LPTSTR lpszIspFile)
|
|
{
|
|
ASSERT(m_pMSHTML);
|
|
|
|
IHTMLElementCollection* pColl = NULL;
|
|
|
|
// retrieve a reference to the ALL collection
|
|
if (SUCCEEDED(m_pMSHTML->get_all( &pColl )))
|
|
{
|
|
LPDISPATCH pDisp = NULL;
|
|
VARIANT varName;
|
|
VARIANT varIdx;
|
|
|
|
VariantInit(&varName);
|
|
V_VT(&varName) = VT_BSTR;
|
|
varName.bstrVal = A2W(HARDCODED_IEAK_ISPFILE_ELEMENT_ID);
|
|
varIdx.vt = VT_UINT;
|
|
varIdx.lVal = 0;
|
|
|
|
if (SUCCEEDED(pColl->item(varName, varIdx, &pDisp)) && pDisp)
|
|
{
|
|
IHTMLElement* pElement = NULL;
|
|
if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLElement, (void**)&pElement)))
|
|
{
|
|
BSTR bstrVal;
|
|
if (SUCCEEDED(pElement->get_innerHTML(&bstrVal)))
|
|
{
|
|
lstrcpy(lpszIspFile, W2A(bstrVal));
|
|
SysFreeString(bstrVal);
|
|
}
|
|
pElement->Release();
|
|
}
|
|
pDisp->Release();
|
|
}
|
|
pColl->Release();
|
|
}
|
|
return S_OK;
|
|
}
|
|
|
|
|
|
void CWalker::GetInputValue
|
|
(
|
|
LPTSTR lpszName,
|
|
BSTR *pVal,
|
|
UINT index,
|
|
IHTMLFormElement *pForm
|
|
)
|
|
{
|
|
VARIANT varName;
|
|
VariantInit(&varName);
|
|
V_VT(&varName) = VT_BSTR;
|
|
varName.bstrVal = A2W(lpszName);
|
|
|
|
VARIANT varIdx;
|
|
varIdx.vt = VT_UINT;
|
|
varIdx.lVal = index;
|
|
|
|
LPDISPATCH pDispElt = NULL;
|
|
// Get the IDispatch for the named element, from the collection of elements in the
|
|
// passed in form object.
|
|
if (SUCCEEDED(pForm->item(varName, varIdx, &pDispElt)) && pDispElt)
|
|
{
|
|
IHTMLInputElement *pInput = NULL;
|
|
// Get the HTMLInputElement interface, so we can get the value associated with
|
|
// this element
|
|
if (SUCCEEDED(pDispElt->QueryInterface(IID_IHTMLInputElement,(LPVOID*) &pInput)) && pInput)
|
|
{
|
|
pInput->get_value(pVal);
|
|
pInput->Release();
|
|
}
|
|
pDispElt->Release();
|
|
}
|
|
}
|
|
|
|
// Grovel through the OLS HTML and update the registry, and make any desktop shortcuts
|
|
HRESULT CWalker::ProcessOLSFile(IWebBrowser2* lpWebBrowser)
|
|
{
|
|
LPDISPATCH pDisp;
|
|
|
|
// Get the document pointer from this webbrowser.
|
|
if (SUCCEEDED(lpWebBrowser->get_Document(&pDisp)))
|
|
{
|
|
// Call might succeed but that dosen't guarantee a valid ptr
|
|
if(pDisp)
|
|
{
|
|
IHTMLDocument2* pDoc;
|
|
if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pDoc)))
|
|
{
|
|
IHTMLElementCollection* pColl = NULL;
|
|
// retrieve a reference to the ALL collection
|
|
if (SUCCEEDED(pDoc->get_all( &pColl )))
|
|
{
|
|
long cElems;
|
|
assert(pColl);
|
|
|
|
// retrieve the count of elements in the collection
|
|
if (SUCCEEDED(pColl->get_length( &cElems )))
|
|
{
|
|
VARIANT vIndex;
|
|
vIndex.vt = VT_UINT;
|
|
VARIANT var2 = { 0 };
|
|
|
|
for ( int i=0; i<cElems; i++ )
|
|
{
|
|
vIndex.lVal = i;
|
|
LPDISPATCH pElementDisp;
|
|
|
|
if (SUCCEEDED(pColl->item( vIndex, var2, &pElementDisp )))
|
|
{
|
|
IHTMLFormElement* pForm = NULL;
|
|
if (SUCCEEDED(pElementDisp->QueryInterface( IID_IHTMLFormElement, (LPVOID*)&pForm )))
|
|
{
|
|
BSTR bstrName = NULL;
|
|
|
|
// Get the name of the form, and see if it is the regEntries form
|
|
if (SUCCEEDED(pForm->get_name(&bstrName)))
|
|
{
|
|
if (lstrcmpi(W2A(bstrName), cszOLSRegEntries) == 0)
|
|
{
|
|
BSTR bstrAction = NULL;
|
|
// The Action value for this form contains the number of
|
|
// reg entries we need to process
|
|
if (SUCCEEDED(pForm->get_action(&bstrAction)))
|
|
{
|
|
int iNumEntries = _ttoi(W2A(bstrAction));
|
|
for (int x = 0; x < iNumEntries; x++)
|
|
{
|
|
BSTR bstrKeyName = NULL;
|
|
BSTR bstrEntryName = NULL;
|
|
BSTR bstrEntryValue = NULL;
|
|
HKEY hkey;
|
|
HKEY hklm;
|
|
|
|
// For each entry we need to get the
|
|
// following values:
|
|
// KeyName, EntryName, EntryValue
|
|
GetInputValue((LPTSTR)cszKeyName, &bstrKeyName, x, pForm);
|
|
GetInputValue((LPTSTR)cszEntryName, &bstrEntryName, x, pForm);
|
|
GetInputValue((LPTSTR)cszEntryValue, &bstrEntryValue, x, pForm);
|
|
|
|
if (bstrKeyName && bstrEntryName && bstrEntryValue)
|
|
{
|
|
if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
|
|
NULL,
|
|
0,
|
|
KEY_ALL_ACCESS,
|
|
&hklm) == ERROR_SUCCESS)
|
|
{
|
|
|
|
DWORD dwDisposition;
|
|
if (ERROR_SUCCESS == RegCreateKeyEx(hklm,
|
|
W2A(bstrKeyName),
|
|
0,
|
|
NULL,
|
|
REG_OPTION_NON_VOLATILE,
|
|
KEY_ALL_ACCESS,
|
|
NULL,
|
|
&hkey,
|
|
&dwDisposition))
|
|
{
|
|
LPTSTR lpszValue = W2A(bstrEntryValue);
|
|
RegSetValueEx(hkey,
|
|
W2A(bstrEntryName),
|
|
0,
|
|
REG_SZ,
|
|
(LPBYTE) lpszValue,
|
|
sizeof(TCHAR)*(lstrlen(lpszValue)+1));
|
|
|
|
RegCloseKey(hkey);
|
|
}
|
|
RegCloseKey(hklm);
|
|
}
|
|
|
|
SysFreeString(bstrKeyName);
|
|
SysFreeString(bstrEntryName);
|
|
SysFreeString(bstrEntryValue);
|
|
}
|
|
}
|
|
SysFreeString(bstrAction);
|
|
}
|
|
}
|
|
else if (lstrcmpi(W2A(bstrName), cszOLSDesktopShortcut) == 0)
|
|
{
|
|
// Need to create a desktop shortcut
|
|
BSTR bstrSourceName = NULL;
|
|
BSTR bstrTargetName = NULL;
|
|
|
|
// For each entry we need to get the
|
|
// following values:
|
|
// KeyName, EntryName, EntryValue
|
|
GetInputValue((LPTSTR)cszSourceName, &bstrSourceName, 0, pForm);
|
|
GetInputValue((LPTSTR)cszTargetName, &bstrTargetName, 0, pForm);
|
|
|
|
if (bstrSourceName && bstrTargetName)
|
|
{
|
|
TCHAR szLinkPath[MAX_PATH];
|
|
TCHAR szDestPath[MAX_PATH];
|
|
LPITEMIDLIST lpItemDList = NULL;
|
|
IMalloc *pMalloc = NULL;
|
|
|
|
// Get a reference to the shell allocator
|
|
if (SUCCEEDED (SHGetMalloc (&pMalloc)))
|
|
{
|
|
if (SUCCEEDED(SHGetSpecialFolderLocation( NULL, CSIDL_PROGRAMS, &lpItemDList)))
|
|
{
|
|
|
|
SHGetPathFromIDList(lpItemDList, szLinkPath);
|
|
lstrcat(szLinkPath, TEXT("\\"));
|
|
lstrcat(szLinkPath, W2A(bstrSourceName));
|
|
|
|
pMalloc->Free (lpItemDList);
|
|
lpItemDList = NULL;
|
|
// Form the name where we will copy to
|
|
if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP,&lpItemDList)))
|
|
{
|
|
SHGetPathFromIDList(lpItemDList, szDestPath);
|
|
pMalloc->Free (lpItemDList);
|
|
|
|
lstrcat(szDestPath, TEXT("\\"));
|
|
lstrcat(szDestPath, W2A(bstrTargetName));
|
|
|
|
CopyFile(szLinkPath, szDestPath, FALSE);
|
|
}
|
|
}
|
|
// Release the allocator
|
|
pMalloc->Release ();
|
|
}
|
|
SysFreeString(bstrSourceName);
|
|
SysFreeString(bstrTargetName);
|
|
}
|
|
}
|
|
|
|
SysFreeString(bstrName);
|
|
}
|
|
pForm->Release();
|
|
}
|
|
pElementDisp->Release();
|
|
} // item
|
|
} // for
|
|
} // get_length
|
|
pColl->Release();
|
|
} // get_all
|
|
pDoc->Release();
|
|
}
|
|
pDisp->Release();
|
|
}
|
|
}
|
|
return S_OK;
|
|
}
|