Source code of Windows XP (NT5)
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
47 KiB

  1. //*********************************************************************
  2. //* Microsoft Windows **
  3. //* Copyright(c) Microsoft Corp., 1994 **
  4. //*********************************************************************
  5. //
  6. // WALKER.CPP - Functions for walking an HTML input file
  7. //
  8. // HISTORY:
  9. //
  10. // 05/13/98 donaldm Created.
  11. //
  12. //*********************************************************************
  13. #include "pre.h"
  14. #include <urlmon.h>
  15. #include <mshtmdid.h>
  16. #include <mshtml.h>
  17. #include <shlobj.h>
  18. const TCHAR cszEquals[] = TEXT("=");
  19. const TCHAR cszAmpersand[] = TEXT("&");
  20. const TCHAR cszPlus[] = TEXT("+");
  21. const TCHAR cszQuestion[] = TEXT("?");
  22. const TCHAR cszFormNamePAGEID[] = TEXT("PAGEID");
  23. const TCHAR cszFormNameBACK[] = TEXT("BACK");
  24. const TCHAR cszFormNamePAGETYPE[] = TEXT("PAGETYPE");
  25. const TCHAR cszFormNameNEXT[] = TEXT("NEXT");
  26. const TCHAR cszFormNamePAGEFLAG[] = TEXT("PAGEFLAG");
  27. const TCHAR cszPageTypeTERMS[] = TEXT("TERMS");
  28. const TCHAR cszPageTypeCUSTOMFINISH[] = TEXT("CUSTOMFINISH");
  29. const TCHAR cszPageTypeFINISH[] = TEXT("FINISH");
  30. const TCHAR cszPageTypeNORMAL[] = TEXT("");
  31. const TCHAR cszOLSRegEntries[] = TEXT("regEntries");
  32. const TCHAR cszKeyName[] = TEXT("KeyName");
  33. const TCHAR cszEntryName[] = TEXT("EntryName");
  34. const TCHAR cszEntryValue[] = TEXT("EntryValue");
  35. const TCHAR cszOLSDesktopShortcut[] = TEXT("DesktopShortcut");
  36. const TCHAR cszSourceName[] = TEXT("SourceName");
  37. const TCHAR cszTargetName[] = TEXT("TargetName");
  38. #define HARDCODED_IEAK_ISPFILE_ELEMENT_ID TEXT("g_IspFilePath")
  39. // COM interfaces
  40. STDMETHODIMP CWalker::QueryInterface(REFIID riid, LPVOID* ppv)
  41. {
  42. *ppv = NULL;
  43. if (IID_IUnknown == riid || IID_IPropertyNotifySink == riid)
  44. {
  45. *ppv = (LPUNKNOWN)(IPropertyNotifySink*)this;
  46. AddRef();
  47. return NOERROR;
  48. }
  49. else if (IID_IOleClientSite == riid)
  50. {
  51. *ppv = (IOleClientSite*)this;
  52. AddRef();
  53. return NOERROR;
  54. }
  55. else if (IID_IDispatch == riid)
  56. {
  57. *ppv = (IDispatch*)this;
  58. AddRef();
  59. return NOERROR;
  60. }
  61. else
  62. {
  63. return E_NOTIMPL;
  64. }
  65. }
  66. STDMETHODIMP_(ULONG) CWalker::AddRef()
  67. {
  68. return ++m_cRef;
  69. }
  70. STDMETHODIMP_(ULONG) CWalker::Release()
  71. {
  72. if (!(--m_cRef))
  73. {
  74. delete this;
  75. }
  76. return m_cRef;
  77. }
  78. // Fired on change of the value of a 'bindable' property
  79. STDMETHODIMP CWalker::OnChanged(DISPID dispID)
  80. {
  81. HRESULT hr;
  82. if (DISPID_READYSTATE == dispID)
  83. {
  84. // check the value of the readystate property
  85. assert(m_pMSHTML);
  86. VARIANT vResult = {0};
  87. EXCEPINFO excepInfo;
  88. UINT uArgErr;
  89. DISPPARAMS dp = {NULL, NULL, 0, 0};
  90. if (SUCCEEDED(hr = m_pMSHTML->Invoke(DISPID_READYSTATE, IID_NULL, LOCALE_SYSTEM_DEFAULT,
  91. DISPATCH_PROPERTYGET, &dp, &vResult, &excepInfo, &uArgErr)))
  92. {
  93. assert(VT_I4 == V_VT(&vResult));
  94. if (READYSTATE_COMPLETE == (READYSTATE)V_I4(&vResult))
  95. SetEvent(m_hEventTridentDone);
  96. VariantClear(&vResult);
  97. }
  98. }
  99. return NOERROR;
  100. }
  101. // MSHTML Queries for the IDispatch interface of the host through the IOleClientSite
  102. // interface that MSHTML is passed through its implementation of IOleObject::SetClientSite()
  103. STDMETHODIMP CWalker::Invoke(DISPID dispIdMember,
  104. REFIID riid,
  105. LCID lcid,
  106. WORD wFlags,
  107. DISPPARAMS __RPC_FAR *pDispParams,
  108. VARIANT __RPC_FAR *pVarResult,
  109. EXCEPINFO __RPC_FAR *pExcepInfo,
  110. UINT __RPC_FAR *puArgErr)
  111. {
  112. if (!pVarResult)
  113. {
  114. return E_POINTER;
  115. }
  116. switch(dispIdMember)
  117. {
  118. case DISPID_AMBIENT_DLCONTROL:
  119. // respond to this ambient to indicate that we only want to
  120. // download the page, but we don't want to run scripts,
  121. // Java applets, or ActiveX controls
  122. V_VT(pVarResult) = VT_I4;
  123. V_I4(pVarResult) = DLCTL_DOWNLOADONLY |
  124. DLCTL_NO_SCRIPTS |
  125. DLCTL_NO_JAVA |
  126. DLCTL_NO_DLACTIVEXCTLS |
  127. DLCTL_NO_RUNACTIVEXCTLS;
  128. break;
  129. default:
  130. return DISP_E_MEMBERNOTFOUND;
  131. }
  132. return NOERROR;
  133. }
  134. // A more traditional form of persistence.
  135. // MSHTML performs this asynchronously as well.
  136. HRESULT CWalker::LoadURLFromFile(BSTR bstrURL)
  137. {
  138. HRESULT hr;
  139. LPPERSISTFILE pPF;
  140. // MSHTML supports file persistence for ordinary files.
  141. if ( SUCCEEDED(hr = m_pMSHTML->QueryInterface(IID_IPersistFile, (LPVOID*) &pPF)))
  142. {
  143. hr = pPF->Load(bstrURL, 0);
  144. pPF->Release();
  145. }
  146. return hr;
  147. }
  148. // Local interfaces
  149. // This function will attached trient to a location FILE: URL, and ensure that it is ready
  150. // to be walked
  151. HRESULT CWalker::InitForMSHTML()
  152. {
  153. HRESULT hr;
  154. LPCONNECTIONPOINTCONTAINER pCPC = NULL;
  155. LPOLEOBJECT pOleObject = NULL;
  156. LPOLECONTROL pOleControl = NULL;
  157. // Create an instance of an dynamic HTML document
  158. if (FAILED(hr = CoCreateInstance( CLSID_HTMLDocument, NULL,
  159. CLSCTX_INPROC_SERVER, IID_IHTMLDocument2,
  160. (LPVOID*)&m_pTrident )))
  161. {
  162. goto Error;
  163. }
  164. if (FAILED(hr = m_pTrident->QueryInterface(IID_IOleObject, (LPVOID*)&pOleObject)))
  165. {
  166. goto Error;
  167. }
  168. hr = pOleObject->SetClientSite((IOleClientSite*)this);
  169. pOleObject->Release();
  170. if (FAILED(hr = m_pTrident->QueryInterface(IID_IOleControl, (LPVOID*)&pOleControl)))
  171. {
  172. goto Error;
  173. }
  174. hr = pOleControl->OnAmbientPropertyChange(DISPID_AMBIENT_DLCONTROL);
  175. pOleControl->Release();
  176. // Hook up sink to catch ready state property change
  177. if (FAILED(hr = m_pTrident->QueryInterface(IID_IConnectionPointContainer, (LPVOID*)&pCPC)))
  178. {
  179. goto Error;
  180. }
  181. if (FAILED(hr = pCPC->FindConnectionPoint(IID_IPropertyNotifySink, &m_pCP)))
  182. {
  183. goto Error;
  184. }
  185. m_hrConnected = m_pCP->Advise((LPUNKNOWN)(IPropertyNotifySink*)this, &m_dwCookie);
  186. Error:
  187. if (pCPC)
  188. pCPC->Release();
  189. return hr;
  190. }
  191. // Clean up connection point
  192. HRESULT CWalker::TermForMSHTML()
  193. {
  194. HRESULT hr = NOERROR;
  195. // Disconnect from property change notifications
  196. if (SUCCEEDED(m_hrConnected))
  197. {
  198. hr = m_pCP->Unadvise(m_dwCookie);
  199. }
  200. // Release the connection point
  201. if (m_pCP)
  202. m_pCP->Release();
  203. if (m_pTrident)
  204. m_pTrident->Release();
  205. return hr;
  206. }
  207. HRESULT CWalker::ExtractUnHiddenText(BSTR* pbstrText)
  208. {
  209. VARIANT vIndex;
  210. LPDISPATCH pDisp;
  211. IHTMLInputHiddenElement* pHidden;
  212. IHTMLElement* pElement;
  213. BSTR bstrValue;
  214. VARIANT var2 = { 0 };
  215. long lLen = 0;
  216. vIndex.vt = VT_UINT;
  217. bstrValue = SysAllocString(A2W(TEXT("\0")));
  218. Walk();
  219. if (!m_pNextForm)
  220. return E_UNEXPECTED;
  221. m_pNextForm->get_length(&lLen);
  222. for (int i = 0; i < lLen; i++)
  223. {
  224. vIndex.lVal = i;
  225. pDisp = NULL;
  226. if(SUCCEEDED(m_pNextForm->item(vIndex, var2, &pDisp)) && pDisp)
  227. {
  228. pHidden = NULL;
  229. if(SUCCEEDED(pDisp->QueryInterface(IID_IHTMLInputHiddenElement, (LPVOID*)&pHidden)) && pHidden)
  230. {
  231. pHidden->put_value(bstrValue);
  232. pHidden->Release();
  233. }
  234. pDisp->Release();
  235. }
  236. }
  237. if (SUCCEEDED(m_pNextForm->QueryInterface(IID_IHTMLElement, (LPVOID*)&pElement)) && pElement)
  238. pElement->get_innerHTML(pbstrText);
  239. SysFreeString(bstrValue);
  240. return S_OK;
  241. }
  242. HRESULT CWalker::AttachToMSHTML(BSTR bstrURL)
  243. {
  244. HRESULT hr;
  245. // Release any previous instance of the HTML document pointer we might be holding on to
  246. if(m_pMSHTML)
  247. {
  248. m_pMSHTML->Release();
  249. m_pMSHTML = NULL;
  250. }
  251. m_pMSHTML = m_pTrident;
  252. m_pMSHTML->AddRef();
  253. m_hEventTridentDone = CreateEvent(NULL, TRUE, FALSE, NULL);
  254. hr = LoadURLFromFile(bstrURL);
  255. if (SUCCEEDED(hr) || (E_PENDING == hr))
  256. {
  257. if (m_hEventTridentDone)
  258. {
  259. MSG msg;
  260. DWORD dwRetCode;
  261. HANDLE hEventList[1];
  262. hEventList[0] = m_hEventTridentDone;
  263. while (TRUE)
  264. {
  265. // We will wait on window messages and also the named event.
  266. dwRetCode = MsgWaitForMultipleObjects(1,
  267. &hEventList[0],
  268. FALSE,
  269. 300000, // 5 minutes
  270. QS_ALLINPUT);
  271. // Determine why we came out of MsgWaitForMultipleObjects(). If
  272. // we timed out then let's do some TrialWatcher work. Otherwise
  273. // process the message that woke us up.
  274. if (WAIT_TIMEOUT == dwRetCode)
  275. {
  276. break;
  277. }
  278. else if (WAIT_OBJECT_0 == dwRetCode)
  279. {
  280. break;
  281. }
  282. else if (WAIT_OBJECT_0 + 1 == dwRetCode)
  283. {
  284. // Process all messages in the Queue, since MsgWaitForMultipleObjects
  285. // will not do this for us
  286. while (TRUE)
  287. {
  288. if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE))
  289. {
  290. if (WM_QUIT == msg.message)
  291. {
  292. break;
  293. }
  294. else
  295. {
  296. TranslateMessage(&msg);
  297. DispatchMessage(&msg);
  298. }
  299. }
  300. else
  301. {
  302. break;
  303. }
  304. }
  305. }
  306. }
  307. CloseHandle(m_hEventTridentDone);
  308. m_hEventTridentDone = 0;
  309. }
  310. else
  311. {
  312. // If we were pending, and we could not wait, we got a problem...
  313. if(E_PENDING == hr)
  314. hr = E_FAIL;
  315. }
  316. }
  317. return (hr);
  318. }
  319. HRESULT CWalker::AttachToDocument(IWebBrowser2 *lpWebBrowser)
  320. {
  321. HRESULT hr;
  322. LPDISPATCH pDisp;
  323. // Release any previous instance of the HTML document pointer we might be holding on to
  324. if(m_pMSHTML)
  325. {
  326. // If the m_pMSHMTL is NOT our internal Trident object (for walking files)
  327. // then sombody did not do a detach, so we need to release the previous
  328. // MSHTML object
  329. if (m_pMSHTML != m_pTrident)
  330. m_pMSHTML->Release();
  331. m_pMSHTML = NULL;
  332. }
  333. // Make sure we have a webbrowser to grab onto
  334. ASSERT(lpWebBrowser);
  335. // Get the document pointer from this webbrowser.
  336. if (SUCCEEDED(hr = lpWebBrowser->get_Document(&pDisp)))
  337. {
  338. if (pDisp)
  339. {
  340. hr = pDisp->QueryInterface( IID_IHTMLDocument2, (LPVOID*)&m_pMSHTML );
  341. // Paranoia, but trident/shdocvw might say OK, but really not give us a document
  342. if (!m_pMSHTML)
  343. hr = E_FAIL;
  344. pDisp->Release();
  345. }
  346. else
  347. {
  348. hr = E_FAIL;
  349. }
  350. }
  351. return (hr);
  352. }
  353. HRESULT CWalker::Detach()
  354. {
  355. if (m_pPageIDForm)
  356. {
  357. m_pPageIDForm->Release();
  358. m_pPageIDForm = NULL;
  359. }
  360. if (m_pBackForm)
  361. {
  362. m_pBackForm->Release();
  363. m_pBackForm = NULL;
  364. }
  365. if (m_pPageTypeForm)
  366. {
  367. m_pPageTypeForm->Release();
  368. m_pPageTypeForm = NULL;
  369. }
  370. if (m_pNextForm)
  371. {
  372. m_pNextForm->Release();
  373. m_pNextForm = NULL;
  374. }
  375. if (m_pPageFlagForm)
  376. {
  377. m_pPageFlagForm->Release();
  378. m_pPageFlagForm = NULL;
  379. }
  380. if(m_pMSHTML)
  381. {
  382. // If the m_pMSHMTL is NOT our internal Trident object (for walking files)
  383. // then sombody did not do a detach, so we need to release the previous
  384. // MSHTML object
  385. if (m_pMSHTML != m_pTrident)
  386. m_pMSHTML->Release();
  387. m_pMSHTML = NULL;
  388. }
  389. return S_OK;
  390. }
  391. // Walk the object model.
  392. HRESULT CWalker::Walk()
  393. {
  394. HRESULT hr;
  395. IHTMLElementCollection* pColl = NULL;
  396. assert(m_pMSHTML);
  397. if (!m_pMSHTML)
  398. {
  399. return E_UNEXPECTED;
  400. }
  401. // retrieve a reference to the ALL collection
  402. if (SUCCEEDED(hr = m_pMSHTML->get_all( &pColl )))
  403. {
  404. long cElems;
  405. assert(pColl);
  406. // retrieve the count of elements in the collection
  407. if (SUCCEEDED(hr = pColl->get_length( &cElems )))
  408. {
  409. // for each element retrieve properties such as TAGNAME and HREF
  410. for ( int i=0; i<cElems; i++ )
  411. {
  412. VARIANT vIndex;
  413. vIndex.vt = VT_UINT;
  414. vIndex.lVal = i;
  415. VARIANT var2 = { 0 };
  416. LPDISPATCH pDisp;
  417. if (SUCCEEDED(hr = pColl->item( vIndex, var2, &pDisp )))
  418. {
  419. // Look for <FORM> tags
  420. IHTMLFormElement* pForm = NULL;
  421. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLFormElement, (LPVOID*)&pForm )))
  422. {
  423. BSTR bstrName;
  424. assert(pForm);
  425. // Get the Name
  426. hr = pForm->get_name(&bstrName);
  427. if (SUCCEEDED(hr))
  428. {
  429. LPTSTR lpszName = W2A(bstrName);
  430. // See what kind it is
  431. if (lstrcmpi(lpszName, cszFormNamePAGEID) == 0)
  432. {
  433. m_pPageIDForm = pForm;
  434. m_pPageIDForm->AddRef();
  435. }
  436. else if (lstrcmpi(lpszName, cszFormNameBACK) == 0)
  437. {
  438. m_pBackForm = pForm;
  439. m_pBackForm->AddRef();
  440. }
  441. else if (lstrcmpi(lpszName, cszFormNamePAGETYPE) == 0)
  442. {
  443. m_pPageTypeForm = pForm;
  444. m_pPageTypeForm->AddRef();
  445. }
  446. else if (lstrcmpi(lpszName, cszFormNameNEXT) == 0)
  447. {
  448. m_pNextForm = pForm;
  449. m_pNextForm->AddRef();
  450. }
  451. else if (lstrcmpi(lpszName, cszFormNamePAGEFLAG) == 0)
  452. {
  453. m_pPageFlagForm = pForm;
  454. m_pPageFlagForm->AddRef();
  455. }
  456. SysFreeString(bstrName);
  457. }
  458. pForm->Release();
  459. }
  460. pDisp->Release();
  461. } // item
  462. } // for
  463. } // get_length
  464. pColl->Release();
  465. } // get_all
  466. return hr;
  467. }
  468. HRESULT CWalker::get_IsQuickFinish(BOOL* pbIsQuickFinish)
  469. {
  470. if (!m_pPageTypeForm)
  471. return (E_FAIL);
  472. IHTMLElement* pElement = NULL;
  473. VARIANT varValue;
  474. VariantInit(&varValue);
  475. V_VT(&varValue) = VT_BSTR;
  476. *pbIsQuickFinish = FALSE;
  477. if (SUCCEEDED(m_pPageTypeForm->QueryInterface(IID_IHTMLElement, (void**)&pElement)))
  478. {
  479. if (SUCCEEDED(pElement->getAttribute(A2W(TEXT("QUICKFINISH")), FALSE, &varValue)))
  480. {
  481. if (VT_NULL != varValue.vt)
  482. {
  483. if(lstrcmpi(W2A(varValue.bstrVal), TEXT("TRUE")) == 0)
  484. *pbIsQuickFinish = TRUE;
  485. }
  486. }
  487. pElement->Release();
  488. }
  489. return S_OK;
  490. }
  491. HRESULT CWalker::get_PageType(LPDWORD pdwPageType)
  492. {
  493. BSTR bstr;
  494. HRESULT hr;
  495. if (!m_pPageTypeForm)
  496. return (E_FAIL);
  497. // Get the Action for the PageType Form
  498. hr = m_pPageTypeForm->get_action(&bstr);
  499. if (SUCCEEDED(hr))
  500. {
  501. LPTSTR lpszType = W2A(bstr);
  502. // See what kind it is
  503. if (lstrcmpi(lpszType, cszPageTypeTERMS) == 0)
  504. *pdwPageType = PAGETYPE_ISP_TOS;
  505. else if (lstrcmpi(lpszType, cszPageTypeCUSTOMFINISH) == 0)
  506. *pdwPageType = PAGETYPE_ISP_CUSTOMFINISH;
  507. else if (lstrcmpi(lpszType, cszPageTypeFINISH) == 0)
  508. *pdwPageType = PAGETYPE_ISP_FINISH;
  509. else if (lstrcmpi(lpszType, cszPageTypeNORMAL) == 0)
  510. *pdwPageType = PAGETYPE_ISP_NORMAL;
  511. else
  512. *pdwPageType = PAGETYPE_UNDEFINED;
  513. SysFreeString(bstr);
  514. }
  515. return (hr);
  516. }
  517. HRESULT CWalker::get_PageFlag(LPDWORD pdwPageFlag)
  518. {
  519. BSTR bstr;
  520. HRESULT hr;
  521. *pdwPageFlag = 0;
  522. if (!m_pPageFlagForm)
  523. return (E_FAIL);
  524. // Get the Action for the PageFlag Form
  525. hr = m_pPageFlagForm->get_action(&bstr);
  526. if (SUCCEEDED(hr))
  527. {
  528. LPTSTR lpszType = W2A(bstr);
  529. // See what kind it is
  530. *pdwPageFlag = _ttol(lpszType);
  531. SysFreeString(bstr);
  532. }
  533. return (hr);
  534. }
  535. HRESULT CWalker::get_PageID(BSTR *pbstrPageID)
  536. {
  537. HRESULT hr;
  538. if (!m_pPageIDForm)
  539. return (E_FAIL);
  540. if (!pbstrPageID)
  541. return (E_FAIL);
  542. // Get the Action for the PageType Form
  543. hr = m_pPageIDForm->get_action(pbstrPageID);
  544. return (hr);
  545. }
  546. HRESULT CWalker::getQueryString
  547. (
  548. IHTMLFormElement *pForm,
  549. LPTSTR lpszQuery
  550. )
  551. {
  552. HRESULT hr;
  553. long lFormLength;
  554. if (SUCCEEDED(pForm->get_length(&lFormLength)))
  555. {
  556. for (int i = 0; i < lFormLength; i++)
  557. {
  558. VARIANT vIndex;
  559. vIndex.vt = VT_UINT;
  560. vIndex.lVal = i;
  561. VARIANT var2 = { 0 };
  562. LPDISPATCH pDisp;
  563. if (SUCCEEDED(hr = pForm->item( vIndex, var2, &pDisp )))
  564. {
  565. // See if the Item is a Input button
  566. IHTMLButtonElement* pButton = NULL;
  567. IHTMLInputButtonElement* pInputButton = NULL;
  568. IHTMLInputFileElement* pInputFile = NULL;
  569. IHTMLInputHiddenElement* pInputHidden = NULL;
  570. IHTMLInputTextElement* pInputText = NULL;
  571. IHTMLSelectElement* pSelect = NULL;
  572. IHTMLTextAreaElement* pTextArea = NULL;
  573. IHTMLOptionButtonElement* pOptionButton = NULL;
  574. // First check to see if this is an OptionButton.
  575. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLOptionButtonElement, (LPVOID*)&pOptionButton )))
  576. {
  577. BSTR bstr = NULL;
  578. // See if it is a Radio or a CheckBox
  579. if (SUCCEEDED(pOptionButton->get_type(&bstr)))
  580. {
  581. LPTSTR lpszType = W2A(bstr);
  582. if ((lstrcmpi(lpszType, TEXT("radio")) == 0) || (lstrcmpi(lpszType, TEXT("checkbox")) == 0))
  583. {
  584. short bChecked;
  585. // See if the button is checked. If it is, then it needs to be
  586. // added to the query string
  587. if (SUCCEEDED(pOptionButton->get_checked(&bChecked)))
  588. {
  589. if(bChecked)
  590. {
  591. BSTR bstrName;
  592. BSTR bstrValue;
  593. if ( SUCCEEDED(pOptionButton->get_name(&bstrName)) &&
  594. SUCCEEDED(pOptionButton->get_value(&bstrValue)) )
  595. {
  596. if (bstrValue)
  597. {
  598. size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
  599. TCHAR* szVal = (TCHAR*)malloc(size * 3);
  600. if (szVal)
  601. {
  602. memcpy(szVal, W2A(bstrValue), size);
  603. URLEncode(szVal, size * 3);
  604. URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
  605. // Cleanup
  606. free(szVal);
  607. }
  608. SysFreeString(bstrName);
  609. SysFreeString(bstrValue);
  610. }
  611. }
  612. }
  613. }
  614. }
  615. SysFreeString(bstr);
  616. }
  617. // Release the interface
  618. pOptionButton->Release();
  619. continue;
  620. }
  621. // For the rest we need to form Name=Value pairs
  622. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLButtonElement, (LPVOID*)&pButton )))
  623. {
  624. BSTR bstrName;
  625. BSTR bstrValue;
  626. if (SUCCEEDED(pButton->get_name(&bstrName)) &&
  627. SUCCEEDED(pButton->get_value(&bstrValue)) )
  628. {
  629. if (bstrValue)
  630. {
  631. size_t size = sizeof(TCHAR) * (lstrlen(W2A(bstrValue)) + 1 );
  632. TCHAR* szVal = (TCHAR*)malloc(size * 3);
  633. if (szVal)
  634. {
  635. memcpy(szVal, W2A(bstrValue), size);
  636. URLEncode(szVal, size * 3);
  637. URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
  638. // Cleanup
  639. free(szVal);
  640. }
  641. SysFreeString(bstrName);
  642. SysFreeString(bstrValue);
  643. }
  644. }
  645. // Release the interface pointer
  646. pButton->Release();
  647. continue;
  648. }
  649. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLInputFileElement, (LPVOID*)&pInputFile )))
  650. {
  651. BSTR bstrName;
  652. BSTR bstrValue;
  653. if (SUCCEEDED(pInputFile->get_name(&bstrName)) &&
  654. SUCCEEDED(pInputFile->get_value(&bstrValue)) )
  655. {
  656. if (bstrValue)
  657. {
  658. size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
  659. TCHAR* szVal = (TCHAR*)malloc(size * 3);
  660. if (szVal)
  661. {
  662. memcpy(szVal, W2A(bstrValue), size);
  663. URLEncode(szVal, size * 3);
  664. URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
  665. // Cleanup
  666. free(szVal);
  667. }
  668. SysFreeString(bstrName);
  669. SysFreeString(bstrValue);
  670. }
  671. }
  672. // Release the interface pointer
  673. pInputFile->Release();
  674. continue;
  675. }
  676. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLInputHiddenElement, (LPVOID*)&pInputHidden )))
  677. {
  678. BSTR bstrName;
  679. BSTR bstrValue;
  680. if (SUCCEEDED(pInputHidden->get_name(&bstrName)) &&
  681. SUCCEEDED(pInputHidden->get_value(&bstrValue)) )
  682. {
  683. if (bstrValue)
  684. {
  685. size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
  686. TCHAR* szVal = (TCHAR*)malloc(size * 3);
  687. if (szVal)
  688. {
  689. memcpy(szVal, W2A(bstrValue), size);
  690. URLEncode(szVal, size * 3);
  691. URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
  692. // Cleanup
  693. free(szVal);
  694. }
  695. SysFreeString(bstrName);
  696. SysFreeString(bstrValue);
  697. }
  698. }
  699. // Release the interface pointer
  700. pInputHidden->Release();
  701. continue;
  702. }
  703. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLInputTextElement, (LPVOID*)&pInputText )))
  704. {
  705. BSTR bstrName;
  706. BSTR bstrValue;
  707. if (SUCCEEDED(pInputText->get_name(&bstrName)) &&
  708. SUCCEEDED(pInputText->get_value(&bstrValue)) )
  709. {
  710. if (bstrValue)
  711. {
  712. size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
  713. TCHAR* szVal = (TCHAR*)malloc(size * 3);
  714. if (szVal)
  715. {
  716. memcpy(szVal, W2A(bstrValue), size);
  717. URLEncode(szVal, size * 3);
  718. URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
  719. // Cleanup
  720. free(szVal);
  721. }
  722. SysFreeString(bstrName);
  723. SysFreeString(bstrValue);
  724. }
  725. }
  726. // Release the interface pointer
  727. pInputText->Release();
  728. continue;
  729. }
  730. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLSelectElement, (LPVOID*)&pSelect )))
  731. {
  732. BSTR bstrName;
  733. BSTR bstrValue;
  734. if (SUCCEEDED(pSelect->get_name(&bstrName)) &&
  735. SUCCEEDED(pSelect->get_value(&bstrValue)) )
  736. {
  737. if (bstrValue)
  738. {
  739. size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
  740. TCHAR* szVal = (TCHAR*)malloc(size * 3);
  741. if (szVal)
  742. {
  743. memcpy(szVal, W2A(bstrValue), size);
  744. URLEncode(szVal, size * 3);
  745. URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
  746. // Cleanup
  747. free(szVal);
  748. }
  749. SysFreeString(bstrName);
  750. SysFreeString(bstrValue);
  751. }
  752. }
  753. // Release the interface pointer
  754. pSelect->Release();
  755. continue;
  756. }
  757. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLTextAreaElement, (LPVOID*)&pTextArea )))
  758. {
  759. BSTR bstrName;
  760. BSTR bstrValue;
  761. if (SUCCEEDED(pTextArea->get_name(&bstrName)) &&
  762. SUCCEEDED(pTextArea->get_value(&bstrValue)) )
  763. {
  764. if (bstrValue)
  765. {
  766. size_t size = sizeof(TCHAR)*(lstrlen(W2A(bstrValue)) + 1);
  767. TCHAR* szVal = (TCHAR*)malloc(size * 3);
  768. if (szVal)
  769. {
  770. memcpy(szVal, W2A(bstrValue), size);
  771. URLEncode(szVal, size * 3);
  772. URLAppendQueryPair(lpszQuery, W2A(bstrName), szVal);
  773. // Cleanup
  774. free(szVal);
  775. }
  776. SysFreeString(bstrName);
  777. SysFreeString(bstrValue);
  778. }
  779. }
  780. // Release the interface pointer
  781. pTextArea->Release();
  782. }
  783. pDisp->Release();
  784. }
  785. }
  786. }
  787. // Null out the last Ampersand, since we don't know when we added the last pair, so we got
  788. // a trailing ampersand
  789. lpszQuery[lstrlen(lpszQuery)-1] = '\0';
  790. return S_OK;
  791. }
  792. HRESULT CWalker::get_FirstFormQueryString
  793. (
  794. LPTSTR lpszQuery
  795. )
  796. {
  797. HRESULT hr;
  798. IHTMLElementCollection *pColl = NULL;
  799. BOOL bDone = FALSE;
  800. assert(m_pMSHTML);
  801. if (!m_pMSHTML)
  802. {
  803. return E_UNEXPECTED;
  804. }
  805. // retrieve a reference to the ALL collection
  806. if (SUCCEEDED(hr = m_pMSHTML->get_all( &pColl )))
  807. {
  808. long cElems;
  809. assert(pColl);
  810. // retrieve the count of elements in the collection
  811. if (SUCCEEDED(hr = pColl->get_length( &cElems )))
  812. {
  813. // for each element retrieve properties such as TAGNAME and HREF
  814. for ( int i=0; (i<cElems) && !bDone; i++ )
  815. {
  816. VARIANT vIndex;
  817. vIndex.vt = VT_UINT;
  818. vIndex.lVal = i;
  819. VARIANT var2 = { 0 };
  820. LPDISPATCH pDisp;
  821. if (SUCCEEDED(hr = pColl->item( vIndex, var2, &pDisp )))
  822. {
  823. // Look for <FORM> tags
  824. IHTMLFormElement* pForm = NULL;
  825. if (SUCCEEDED(hr = pDisp->QueryInterface( IID_IHTMLFormElement, (LPVOID*)&pForm )))
  826. {
  827. assert(pForm);
  828. if (SUCCEEDED(getQueryString(pForm, lpszQuery)))
  829. {
  830. hr = ERROR_SUCCESS;
  831. }
  832. else
  833. {
  834. hr = E_FAIL;
  835. }
  836. pForm->Release();
  837. bDone = TRUE;
  838. }
  839. pDisp->Release();
  840. }
  841. }
  842. }
  843. pColl->Release();
  844. }
  845. // If we fall out of the loop, that is bad, so return a failure code
  846. if (!bDone)
  847. hr = E_FAIL;
  848. return (hr);
  849. }
  850. // For the URL for the next page
  851. HRESULT CWalker::get_URL
  852. (
  853. LPTSTR lpszURL,
  854. BOOL bForward
  855. )
  856. {
  857. HRESULT hr = S_OK;
  858. BSTR bstrURL;
  859. TCHAR szQuery[INTERNET_MAX_URL_LENGTH];
  860. IHTMLFormElement * pForm = bForward ? get_pNextForm() : get_pBackForm();
  861. if (!pForm)
  862. return (E_FAIL);
  863. // Get the Action for the Next Form
  864. hr = pForm->get_action(&bstrURL);
  865. if (SUCCEEDED(hr))
  866. {
  867. memset(szQuery, 0, sizeof(szQuery));
  868. lstrcpy(szQuery, cszQuestion);
  869. // Get the Query String
  870. if (SUCCEEDED(getQueryString(pForm, szQuery)))
  871. {
  872. // Catenate the two together into the dest buffer
  873. lstrcpy(lpszURL, W2A(bstrURL));
  874. lstrcat(lpszURL, szQuery);
  875. }
  876. SysFreeString(bstrURL);
  877. }
  878. return hr;
  879. }
  880. HRESULT CWalker::get_IeakIspFile(LPTSTR lpszIspFile)
  881. {
  882. ASSERT(m_pMSHTML);
  883. IHTMLElementCollection* pColl = NULL;
  884. // retrieve a reference to the ALL collection
  885. if (SUCCEEDED(m_pMSHTML->get_all( &pColl )))
  886. {
  887. LPDISPATCH pDisp = NULL;
  888. VARIANT varName;
  889. VARIANT varIdx;
  890. VariantInit(&varName);
  891. V_VT(&varName) = VT_BSTR;
  892. varName.bstrVal = A2W(HARDCODED_IEAK_ISPFILE_ELEMENT_ID);
  893. varIdx.vt = VT_UINT;
  894. varIdx.lVal = 0;
  895. if (SUCCEEDED(pColl->item(varName, varIdx, &pDisp)) && pDisp)
  896. {
  897. IHTMLElement* pElement = NULL;
  898. if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLElement, (void**)&pElement)))
  899. {
  900. BSTR bstrVal;
  901. if (SUCCEEDED(pElement->get_innerHTML(&bstrVal)))
  902. {
  903. lstrcpy(lpszIspFile, W2A(bstrVal));
  904. SysFreeString(bstrVal);
  905. }
  906. pElement->Release();
  907. }
  908. pDisp->Release();
  909. }
  910. pColl->Release();
  911. }
  912. return S_OK;
  913. }
  914. void CWalker::GetInputValue
  915. (
  916. LPTSTR lpszName,
  917. BSTR *pVal,
  918. UINT index,
  919. IHTMLFormElement *pForm
  920. )
  921. {
  922. VARIANT varName;
  923. VariantInit(&varName);
  924. V_VT(&varName) = VT_BSTR;
  925. varName.bstrVal = A2W(lpszName);
  926. VARIANT varIdx;
  927. varIdx.vt = VT_UINT;
  928. varIdx.lVal = index;
  929. LPDISPATCH pDispElt = NULL;
  930. // Get the IDispatch for the named element, from the collection of elements in the
  931. // passed in form object.
  932. if (SUCCEEDED(pForm->item(varName, varIdx, &pDispElt)) && pDispElt)
  933. {
  934. IHTMLInputElement *pInput = NULL;
  935. // Get the HTMLInputElement interface, so we can get the value associated with
  936. // this element
  937. if (SUCCEEDED(pDispElt->QueryInterface(IID_IHTMLInputElement,(LPVOID*) &pInput)) && pInput)
  938. {
  939. pInput->get_value(pVal);
  940. pInput->Release();
  941. }
  942. pDispElt->Release();
  943. }
  944. }
  945. // Grovel through the OLS HTML and update the registry, and make any desktop shortcuts
  946. HRESULT CWalker::ProcessOLSFile(IWebBrowser2* lpWebBrowser)
  947. {
  948. LPDISPATCH pDisp;
  949. // Get the document pointer from this webbrowser.
  950. if (SUCCEEDED(lpWebBrowser->get_Document(&pDisp)))
  951. {
  952. // Call might succeed but that dosen't guarantee a valid ptr
  953. if(pDisp)
  954. {
  955. IHTMLDocument2* pDoc;
  956. if (SUCCEEDED(pDisp->QueryInterface(IID_IHTMLDocument2, (void**)&pDoc)))
  957. {
  958. IHTMLElementCollection* pColl = NULL;
  959. // retrieve a reference to the ALL collection
  960. if (SUCCEEDED(pDoc->get_all( &pColl )))
  961. {
  962. long cElems;
  963. assert(pColl);
  964. // retrieve the count of elements in the collection
  965. if (SUCCEEDED(pColl->get_length( &cElems )))
  966. {
  967. VARIANT vIndex;
  968. vIndex.vt = VT_UINT;
  969. VARIANT var2 = { 0 };
  970. for ( int i=0; i<cElems; i++ )
  971. {
  972. vIndex.lVal = i;
  973. LPDISPATCH pElementDisp;
  974. if (SUCCEEDED(pColl->item( vIndex, var2, &pElementDisp )))
  975. {
  976. IHTMLFormElement* pForm = NULL;
  977. if (SUCCEEDED(pElementDisp->QueryInterface( IID_IHTMLFormElement, (LPVOID*)&pForm )))
  978. {
  979. BSTR bstrName = NULL;
  980. // Get the name of the form, and see if it is the regEntries form
  981. if (SUCCEEDED(pForm->get_name(&bstrName)))
  982. {
  983. if (lstrcmpi(W2A(bstrName), cszOLSRegEntries) == 0)
  984. {
  985. BSTR bstrAction = NULL;
  986. // The Action value for this form contains the number of
  987. // reg entries we need to process
  988. if (SUCCEEDED(pForm->get_action(&bstrAction)))
  989. {
  990. int iNumEntries = _ttoi(W2A(bstrAction));
  991. for (int x = 0; x < iNumEntries; x++)
  992. {
  993. BSTR bstrKeyName = NULL;
  994. BSTR bstrEntryName = NULL;
  995. BSTR bstrEntryValue = NULL;
  996. HKEY hkey;
  997. HKEY hklm;
  998. // For each entry we need to get the
  999. // following values:
  1000. // KeyName, EntryName, EntryValue
  1001. GetInputValue((LPTSTR)cszKeyName, &bstrKeyName, x, pForm);
  1002. GetInputValue((LPTSTR)cszEntryName, &bstrEntryName, x, pForm);
  1003. GetInputValue((LPTSTR)cszEntryValue, &bstrEntryValue, x, pForm);
  1004. if (bstrKeyName && bstrEntryName && bstrEntryValue)
  1005. {
  1006. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  1007. NULL,
  1008. 0,
  1009. KEY_ALL_ACCESS,
  1010. &hklm) == ERROR_SUCCESS)
  1011. {
  1012. DWORD dwDisposition;
  1013. if (ERROR_SUCCESS == RegCreateKeyEx(hklm,
  1014. W2A(bstrKeyName),
  1015. 0,
  1016. NULL,
  1017. REG_OPTION_NON_VOLATILE,
  1018. KEY_ALL_ACCESS,
  1019. NULL,
  1020. &hkey,
  1021. &dwDisposition))
  1022. {
  1023. LPTSTR lpszValue = W2A(bstrEntryValue);
  1024. RegSetValueEx(hkey,
  1025. W2A(bstrEntryName),
  1026. 0,
  1027. REG_SZ,
  1028. (LPBYTE) lpszValue,
  1029. sizeof(TCHAR)*(lstrlen(lpszValue)+1));
  1030. RegCloseKey(hkey);
  1031. }
  1032. RegCloseKey(hklm);
  1033. }
  1034. SysFreeString(bstrKeyName);
  1035. SysFreeString(bstrEntryName);
  1036. SysFreeString(bstrEntryValue);
  1037. }
  1038. }
  1039. SysFreeString(bstrAction);
  1040. }
  1041. }
  1042. else if (lstrcmpi(W2A(bstrName), cszOLSDesktopShortcut) == 0)
  1043. {
  1044. // Need to create a desktop shortcut
  1045. BSTR bstrSourceName = NULL;
  1046. BSTR bstrTargetName = NULL;
  1047. // For each entry we need to get the
  1048. // following values:
  1049. // KeyName, EntryName, EntryValue
  1050. GetInputValue((LPTSTR)cszSourceName, &bstrSourceName, 0, pForm);
  1051. GetInputValue((LPTSTR)cszTargetName, &bstrTargetName, 0, pForm);
  1052. if (bstrSourceName && bstrTargetName)
  1053. {
  1054. TCHAR szLinkPath[MAX_PATH];
  1055. TCHAR szDestPath[MAX_PATH];
  1056. LPITEMIDLIST lpItemDList = NULL;
  1057. IMalloc *pMalloc = NULL;
  1058. // Get a reference to the shell allocator
  1059. if (SUCCEEDED (SHGetMalloc (&pMalloc)))
  1060. {
  1061. if (SUCCEEDED(SHGetSpecialFolderLocation( NULL, CSIDL_PROGRAMS, &lpItemDList)))
  1062. {
  1063. SHGetPathFromIDList(lpItemDList, szLinkPath);
  1064. lstrcat(szLinkPath, TEXT("\\"));
  1065. lstrcat(szLinkPath, W2A(bstrSourceName));
  1066. pMalloc->Free (lpItemDList);
  1067. lpItemDList = NULL;
  1068. // Form the name where we will copy to
  1069. if (SUCCEEDED(SHGetSpecialFolderLocation(NULL, CSIDL_DESKTOP,&lpItemDList)))
  1070. {
  1071. SHGetPathFromIDList(lpItemDList, szDestPath);
  1072. pMalloc->Free (lpItemDList);
  1073. lstrcat(szDestPath, TEXT("\\"));
  1074. lstrcat(szDestPath, W2A(bstrTargetName));
  1075. CopyFile(szLinkPath, szDestPath, FALSE);
  1076. }
  1077. }
  1078. // Release the allocator
  1079. pMalloc->Release ();
  1080. }
  1081. SysFreeString(bstrSourceName);
  1082. SysFreeString(bstrTargetName);
  1083. }
  1084. }
  1085. SysFreeString(bstrName);
  1086. }
  1087. pForm->Release();
  1088. }
  1089. pElementDisp->Release();
  1090. } // item
  1091. } // for
  1092. } // get_length
  1093. pColl->Release();
  1094. } // get_all
  1095. pDoc->Release();
  1096. }
  1097. pDisp->Release();
  1098. }
  1099. }
  1100. return S_OK;
  1101. }