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.

1718 lines
41 KiB

  1. //+------------------------------------------------------------------------
  2. //
  3. // File : Utils.cxx
  4. //
  5. // purpose : implementation of helpful stuff
  6. //
  7. //-------------------------------------------------------------------------
  8. #include "headers.h"
  9. #pragma MARK_DATA(__FILE__)
  10. #pragma MARK_CODE(__FILE__)
  11. #pragma MARK_CONST(__FILE__)
  12. #include "utils.hxx"
  13. #include <docobj.h>
  14. #include <mshtmcid.h>
  15. #include <mshtmhst.h>
  16. #define BUFFEREDSTR_SIZE 1024
  17. // VARIANT conversion interface exposed by script engines (VBScript/JScript).
  18. EXTERN_C const GUID SID_VariantConversion =
  19. { 0x1f101481, 0xbccd, 0x11d0, { 0x93, 0x36, 0x0, 0xa0, 0xc9, 0xd, 0xca, 0xa9 } };
  20. //+------------------------------------------------------------------------
  21. //
  22. // Function: GetHTMLDocument
  23. //
  24. // Synopsis: Gets the IHTMLDocument2 interface from the client site.
  25. //
  26. //-------------------------------------------------------------------------
  27. STDMETHODIMP
  28. GetHTMLDocument(IElementBehaviorSite * pSite, IHTMLDocument2 **ppDoc)
  29. {
  30. HRESULT hr = E_FAIL;
  31. if (!ppDoc)
  32. return E_POINTER;
  33. if (pSite != NULL)
  34. {
  35. IHTMLElement *pElement = NULL;
  36. hr = pSite->GetElement(&pElement);
  37. if (SUCCEEDED(hr))
  38. {
  39. IDispatch * pDispDoc = NULL;
  40. hr = pElement->get_document(&pDispDoc);
  41. if (SUCCEEDED(hr))
  42. {
  43. hr = pDispDoc->QueryInterface(IID_IHTMLDocument2, (void **)ppDoc);
  44. pDispDoc->Release();
  45. }
  46. pElement->Release();
  47. }
  48. }
  49. return hr;
  50. }
  51. //+------------------------------------------------------------------------
  52. //
  53. // Function: GetHTMLWindow
  54. //
  55. // Synopsis: Gets the IHTMLWindow2 interface from the client site.
  56. //
  57. //-------------------------------------------------------------------------
  58. STDMETHODIMP
  59. GetHTMLWindow(IElementBehaviorSite * pSite, IHTMLWindow2 **ppWindow)
  60. {
  61. HRESULT hr = E_FAIL;
  62. IHTMLDocument2 *pDoc = NULL;
  63. hr = GetHTMLDocument(pSite, &pDoc);
  64. if (SUCCEEDED(hr))
  65. {
  66. hr = pDoc->get_parentWindow(ppWindow);
  67. pDoc->Release();
  68. }
  69. return hr;
  70. }
  71. //+------------------------------------------------------------------------
  72. //
  73. // Function: GetClientSiteWindow
  74. //
  75. // Synopsis: Gets the window handle of the client site passed in.
  76. //
  77. //-------------------------------------------------------------------------
  78. STDMETHODIMP
  79. GetClientSiteWindow(IElementBehaviorSite *pSite, HWND *phWnd)
  80. {
  81. HRESULT hr = E_FAIL;
  82. IWindowForBindingUI *pWindowForBindingUI = NULL;
  83. if (pSite != NULL) {
  84. // Get IWindowForBindingUI ptr
  85. hr = pSite->QueryInterface(IID_IWindowForBindingUI,
  86. (LPVOID *)&pWindowForBindingUI);
  87. if (FAILED(hr)) {
  88. IServiceProvider *pServProv;
  89. hr = pSite->QueryInterface(IID_IServiceProvider, (LPVOID *)&pServProv);
  90. if (hr == NOERROR) {
  91. pServProv->QueryService(IID_IWindowForBindingUI,IID_IWindowForBindingUI,
  92. (LPVOID *)&pWindowForBindingUI);
  93. pServProv->Release();
  94. }
  95. }
  96. if (pWindowForBindingUI) {
  97. pWindowForBindingUI->GetWindow(IID_IWindowForBindingUI, phWnd);
  98. pWindowForBindingUI->Release();
  99. }
  100. }
  101. return hr;
  102. }
  103. //+------------------------------------------------------------------------
  104. //
  105. // Function: AppendElement
  106. //
  107. // Synopsis: Appends a child to an owner
  108. //
  109. //-------------------------------------------------------------------------
  110. STDMETHODIMP
  111. AppendChild(IHTMLElement *pOwner, IHTMLElement *pChild)
  112. {
  113. HRESULT hr;
  114. CComPtr<IHTMLDOMNode> pOwnerNode, pChildNode;
  115. hr = pOwner->QueryInterface(IID_IHTMLDOMNode, (void **) &pOwnerNode);
  116. if (FAILED(hr))
  117. goto Cleanup;
  118. hr = pChild->QueryInterface(IID_IHTMLDOMNode, (void **) &pChildNode);
  119. if (FAILED(hr))
  120. goto Cleanup;
  121. hr = pOwnerNode->appendChild(pChildNode, NULL);
  122. if (FAILED(hr))
  123. goto Cleanup;
  124. Cleanup:
  125. return hr;
  126. }
  127. //+---------------------------------------------------------------
  128. //
  129. // Function: IsSameObject
  130. //
  131. // Synopsis: Checks for COM identity
  132. //
  133. // Arguments: pUnkLeft, pUnkRight
  134. //
  135. //+---------------------------------------------------------------
  136. BOOL
  137. IsSameObject(IUnknown *pUnkLeft, IUnknown *pUnkRight)
  138. {
  139. IUnknown *pUnk1, *pUnk2;
  140. if (pUnkLeft == pUnkRight)
  141. return TRUE;
  142. if (pUnkLeft == NULL || pUnkRight == NULL)
  143. return FALSE;
  144. if (SUCCEEDED(pUnkLeft->QueryInterface(IID_IUnknown, (LPVOID *)&pUnk1)))
  145. {
  146. pUnk1->Release();
  147. if (pUnk1 == pUnkRight)
  148. return TRUE;
  149. if (SUCCEEDED(pUnkRight->QueryInterface(IID_IUnknown, (LPVOID *)&pUnk2)))
  150. {
  151. pUnk2->Release();
  152. return pUnk1 == pUnk2;
  153. }
  154. }
  155. return FALSE;
  156. }
  157. //+------------------------------------------------------------------------
  158. //
  159. // Function: ClearInterfaceFn
  160. //
  161. // Synopsis: Sets an interface pointer to NULL, after first calling
  162. // Release if the pointer was not NULL initially
  163. //
  164. // Arguments: [ppUnk] *ppUnk is cleared
  165. //
  166. //-------------------------------------------------------------------------
  167. void
  168. ClearInterfaceFn(IUnknown ** ppUnk)
  169. {
  170. IUnknown * pUnk;
  171. pUnk = *ppUnk;
  172. *ppUnk = NULL;
  173. if (pUnk)
  174. pUnk->Release();
  175. }
  176. //+------------------------------------------------------------------------
  177. //
  178. // Function: ReplaceInterfaceFn
  179. //
  180. // Synopsis: Replaces an interface pointer with a new interface,
  181. // following proper ref counting rules:
  182. //
  183. // = *ppUnk is set to pUnk
  184. // = if *ppUnk was not NULL initially, it is Release'd
  185. // = if pUnk is not NULL, it is AddRef'd
  186. //
  187. // Effectively, this allows pointer assignment for ref-counted
  188. // pointers.
  189. //
  190. // Arguments: [ppUnk]
  191. // [pUnk]
  192. //
  193. //-------------------------------------------------------------------------
  194. void
  195. ReplaceInterfaceFn(IUnknown ** ppUnk, IUnknown * pUnk)
  196. {
  197. IUnknown * pUnkOld = *ppUnk;
  198. *ppUnk = pUnk;
  199. // Note that we do AddRef before Release; this avoids
  200. // accidentally destroying an object if this function
  201. // is passed two aliases to it
  202. if (pUnk)
  203. pUnk->AddRef();
  204. if (pUnkOld)
  205. pUnkOld->Release();
  206. }
  207. //+------------------------------------------------------------------------
  208. //
  209. // Function: ReleaseInterface
  210. //
  211. // Synopsis: Releases an interface pointer if it is non-NULL
  212. //
  213. // Arguments: [pUnk]
  214. //
  215. //-------------------------------------------------------------------------
  216. void
  217. ReleaseInterface(IUnknown * pUnk)
  218. {
  219. if (pUnk)
  220. pUnk->Release();
  221. }
  222. //+------------------------------------------------------------------------
  223. //
  224. // Member: CBufferedStr::Set
  225. //
  226. // Synopsis: Initilizes a CBufferedStr
  227. //
  228. //-------------------------------------------------------------------------
  229. HRESULT
  230. CBufferedStr::Set (LPCTSTR pch, UINT uiCch)
  231. {
  232. HRESULT hr = S_OK;
  233. Free();
  234. if (!uiCch)
  235. _cchIndex = pch ? _tcslen (pch) : 0;
  236. else
  237. _cchIndex = uiCch;
  238. _cchBufSize = _cchIndex > BUFFEREDSTR_SIZE ? _cchIndex : BUFFEREDSTR_SIZE;
  239. _pchBuf = new TCHAR [ _cchBufSize ];
  240. if (!_pchBuf)
  241. {
  242. hr = E_OUTOFMEMORY;
  243. goto Cleanup;
  244. }
  245. if (pch)
  246. {
  247. _tcsncpy (_pchBuf, pch, _cchIndex);
  248. }
  249. _pchBuf[_cchIndex] = '\0';
  250. Cleanup:
  251. return (hr);
  252. }
  253. //+------------------------------------------------------------------------
  254. //
  255. // Member: CBufferedStr::QuickAppend
  256. //
  257. // Parameters: pchNewStr string to be added to _pchBuf
  258. //
  259. // Synopsis: Appends pNewStr into _pchBuf starting at
  260. // _pchBuf[uIndex]. Increments index to reference
  261. // new end of string. If _pchBuf is not large enough,
  262. // reallocs _pchBuf and updates _cchBufSize.
  263. //
  264. //-------------------------------------------------------------------------
  265. HRESULT
  266. CBufferedStr::QuickAppend (const TCHAR* pchNewStr, ULONG newLen)
  267. {
  268. HRESULT hr = S_OK;
  269. if (!_pchBuf)
  270. {
  271. hr = Set();
  272. if (hr)
  273. goto Cleanup;
  274. }
  275. if (_cchIndex + newLen >= _cchBufSize) // we can't fit the new string in the current buffer
  276. { // so allocate a new buffer, and copy the old string
  277. _cchBufSize += (newLen > BUFFEREDSTR_SIZE) ? newLen : BUFFEREDSTR_SIZE;
  278. TCHAR * pchTemp = new TCHAR [ _cchBufSize ];
  279. if (!pchTemp)
  280. {
  281. hr = E_OUTOFMEMORY;
  282. goto Cleanup;
  283. }
  284. _tcsncpy (pchTemp, _pchBuf, _cchIndex);
  285. Free();
  286. _pchBuf = pchTemp;
  287. }
  288. // append the new string
  289. _tcsncpy (_pchBuf + _cchIndex, pchNewStr, newLen);
  290. _cchIndex += newLen;
  291. _pchBuf[_cchIndex] = '\0';
  292. Cleanup:
  293. return (hr);
  294. }
  295. HRESULT
  296. CBufferedStr::QuickAppend(long lValue)
  297. {
  298. TCHAR strValue[40];
  299. #ifdef UNICODE
  300. return QuickAppend( _ltow(lValue, strValue, 10) );
  301. #else
  302. return QuickAppend( _ltoa(lValue, strValue, 10) );
  303. #endif
  304. }
  305. //+---------------------------------------------------------------------------
  306. //
  307. // method : ConvertGmtTimeToString
  308. //
  309. // Synopsis: This function produces a standard(?) format date, of the form
  310. // Tue, 02 Apr 1996 02:04:57 UTC The date format *will not* be tailored
  311. // for the locale. This is for cookie use and Netscape compatibility
  312. //
  313. //----------------------------------------------------------------------------
  314. static const TCHAR* achMonth[] = {
  315. _T("Jan"),_T("Feb"),_T("Mar"),_T("Apr"),_T("May"),_T("Jun"),
  316. _T("Jul"),_T("Aug"),_T("Sep"),_T("Oct"),_T("Nov"),_T("Dec")
  317. };
  318. static const TCHAR* achDay[] = {
  319. _T("Sun"), _T("Mon"),_T("Tue"),_T("Wed"),_T("Thu"),_T("Fri"),_T("Sat")
  320. };
  321. HRESULT
  322. ConvertGmtTimeToString(FILETIME Time, TCHAR * pchDateStr, DWORD cchDateStr)
  323. {
  324. SYSTEMTIME SystemTime;
  325. CBufferedStr strBuf;
  326. if (cchDateStr < DATE_STR_LENGTH)
  327. return E_INVALIDARG;
  328. FileTimeToSystemTime(&Time, &SystemTime);
  329. strBuf.QuickAppend(achDay[SystemTime.wDayOfWeek]);
  330. strBuf.QuickAppend(_T(", "));
  331. strBuf.QuickAppend(SystemTime.wDay);
  332. strBuf.QuickAppend(_T(" ") );
  333. strBuf.QuickAppend(achMonth[SystemTime.wMonth - 1] );
  334. strBuf.QuickAppend(_T(" ") );
  335. strBuf.QuickAppend(SystemTime.wYear );
  336. strBuf.QuickAppend(_T(" ") );
  337. strBuf.QuickAppend(SystemTime.wHour );
  338. strBuf.QuickAppend(_T(":") );
  339. strBuf.QuickAppend(SystemTime.wMinute );
  340. strBuf.QuickAppend(_T(":") );
  341. strBuf.QuickAppend(SystemTime.wSecond );
  342. strBuf.QuickAppend(_T(" UTC") );
  343. if (strBuf.Length() >cchDateStr)
  344. return E_FAIL;
  345. _tcscpy(pchDateStr, strBuf);
  346. return S_OK;
  347. }
  348. HRESULT
  349. ParseDate(BSTR strDate, FILETIME * pftTime)
  350. {
  351. HRESULT hr = S_FALSE;
  352. SYSTEMTIME stTime ={0};
  353. LPCTSTR pszToken = NULL;
  354. BOOL fFound;
  355. int idx, cch;
  356. CDataListEnumerator dle(strDate, _T(':'));
  357. if (!pftTime)
  358. {
  359. hr = E_POINTER;
  360. goto Cleanup;
  361. }
  362. // get the dayOfTheWeek: 3 digits max plus comma
  363. //--------------------------------------------------
  364. if (! dle.GetNext(&pszToken, &cch) || cch > 4)
  365. goto Cleanup;
  366. else
  367. {
  368. for (idx=0; idx < ARRAY_SIZE(achDay); idx++)
  369. {
  370. fFound = !_tcsnicmp( pszToken, achDay[idx], 3);
  371. if (fFound)
  372. {
  373. stTime.wDayOfWeek = (WORD)idx;
  374. break;
  375. }
  376. }
  377. if (!fFound)
  378. {
  379. hr = E_FAIL;
  380. goto Cleanup;
  381. }
  382. }
  383. // get the Day 2 digits max
  384. //--------------------------------------------------
  385. if (! dle.GetNext(&pszToken, &cch) || cch > 2)
  386. goto Cleanup;
  387. stTime.wDay = (WORD)_ttoi(pszToken);
  388. // get the Month: 3 characters
  389. //--------------------------------------------------
  390. if (! dle.GetNext(&pszToken, &cch) || cch > 3)
  391. goto Cleanup;
  392. else
  393. {
  394. for (idx=0; idx < ARRAY_SIZE(achMonth); idx++)
  395. {
  396. fFound = !_tcsnicmp( pszToken, achMonth[idx], 3);
  397. if (fFound)
  398. {
  399. stTime.wMonth = (WORD)idx + 1;
  400. break;
  401. }
  402. }
  403. if (!fFound)
  404. {
  405. hr = E_FAIL;
  406. goto Cleanup;
  407. }
  408. }
  409. // get the Year 4 digits max
  410. //--------------------------------------------------
  411. if (! dle.GetNext(&pszToken, &cch) || cch > 4)
  412. goto Cleanup;
  413. stTime.wYear = (WORD)_ttoi(pszToken);
  414. // get the Hour 2 digits max
  415. //--------------------------------------------------
  416. if (! dle.GetNext(&pszToken, &cch) || cch > 2)
  417. goto Cleanup;
  418. stTime.wHour = (WORD)_ttoi(pszToken);
  419. // get the Minute 2 digits max
  420. //--------------------------------------------------
  421. if (! dle.GetNext(&pszToken, &cch) || cch > 2)
  422. goto Cleanup;
  423. stTime.wMinute = (WORD)_ttoi(pszToken);
  424. // get the Second 2 digits max
  425. //--------------------------------------------------
  426. if (! dle.GetNext(&pszToken, &cch) || cch > 2)
  427. goto Cleanup;
  428. stTime.wSecond = (WORD)_ttoi(pszToken);
  429. // now we have SYSTEMTIME, lets return the FILETIME
  430. if (!SystemTimeToFileTime(&stTime, pftTime))
  431. hr = GetLastError();
  432. else
  433. hr = S_OK;
  434. Cleanup:
  435. return hr;
  436. }
  437. //+---------------------------------------------------------------------------
  438. //
  439. // Function: MbcsFromUnicode
  440. //
  441. // Synopsis: Converts a string to MBCS from Unicode.
  442. //
  443. // Arguments: [pstr] -- The buffer for the MBCS string.
  444. // [cch] -- The size of the MBCS buffer, including space for
  445. // NULL terminator.
  446. //
  447. // [pwstr] -- The Unicode string to convert.
  448. // [cwch] -- The number of characters in the Unicode string to
  449. // convert, including NULL terminator. If this
  450. // number is -1, the string is assumed to be
  451. // NULL terminated. -1 is supplied as a
  452. // default argument.
  453. //
  454. // Returns: If [pstr] is NULL or [cch] is 0, 0 is returned. Otherwise,
  455. // the number of characters converted, including the terminating
  456. // NULL, is returned (note that converting the empty string will
  457. // return 1). If the conversion fails, 0 is returned.
  458. //
  459. // Modifies: [pstr].
  460. //
  461. //----------------------------------------------------------------------------
  462. int
  463. MbcsFromUnicode(LPSTR pstr, int cch, LPCWSTR pwstr, int cwch)
  464. {
  465. int ret;
  466. #if DBG == 1 /* { */
  467. int errcode;
  468. #endif /* } */
  469. if (!pstr || cch <= 0 || !pwstr || cwch<-1)
  470. return 0;
  471. ret = WideCharToMultiByte(CP_ACP, 0, pwstr, cwch, pstr, cch, NULL, NULL);
  472. #if DBG == 1 /* { */
  473. if (ret <= 0)
  474. {
  475. errcode = GetLastError();
  476. }
  477. #endif /* } */
  478. return ret;
  479. }
  480. //+---------------------------------------------------------------------------
  481. //
  482. // Function: UnicodeFromMbcs
  483. //
  484. // Synopsis: Converts a string to Unicode from MBCS.
  485. //
  486. // Arguments: [pwstr] -- The buffer for the Unicode string.
  487. // [cwch] -- The size of the Unicode buffer, including space for
  488. // NULL terminator.
  489. //
  490. // [pstr] -- The MBCS string to convert.
  491. // [cch] -- The number of characters in the MBCS string to
  492. // convert, including NULL terminator. If this
  493. // number is -1, the string is assumed to be
  494. // NULL terminated. -1 is supplied as a
  495. // default argument.
  496. //
  497. // Returns: If [pwstr] is NULL or [cwch] is 0, 0 is returned. Otherwise,
  498. // the number of characters converted, including the terminating
  499. // NULL, is returned (note that converting the empty string will
  500. // return 1). If the conversion fails, 0 is returned.
  501. //
  502. // Modifies: [pwstr].
  503. //
  504. //----------------------------------------------------------------------------
  505. int
  506. UnicodeFromMbcs(LPWSTR pwstr, int cwch, LPCSTR pstr, int cch)
  507. {
  508. int ret;
  509. #if DBG == 1 /* { */
  510. int errcode;
  511. #endif /* } */
  512. if (!pstr || cwch <= 0 || !pwstr || cch<-1)
  513. return 0;
  514. ret = MultiByteToWideChar(CP_ACP, 0, pstr, cch, pwstr, cwch);
  515. #if DBG == 1 /* { */
  516. if (ret <= 0)
  517. {
  518. errcode = GetLastError();
  519. }
  520. #endif /* } */
  521. return ret;
  522. }
  523. //+--------------------------------------------------------------------
  524. //
  525. // Function: _tcsistr
  526. //
  527. //---------------------------------------------------------------------
  528. const TCHAR * __cdecl _tcsistr (const TCHAR * tcs1,const TCHAR * tcs2)
  529. {
  530. const TCHAR *cp;
  531. int cc,count;
  532. int n2Len = _tcslen ( tcs2 );
  533. int n1Len = _tcslen ( tcs1 );
  534. if ( n1Len >= n2Len )
  535. {
  536. for ( cp = tcs1, count = n1Len - n2Len; count>=0 ; cp++,count-- )
  537. {
  538. cc = CompareString(LCID_SCRIPTING,
  539. NORM_IGNORECASE | NORM_IGNOREWIDTH | NORM_IGNOREKANATYPE,
  540. cp, n2Len,tcs2, n2Len);
  541. if ( cc > 0 )
  542. cc-=2;
  543. if ( !cc )
  544. return cp;
  545. }
  546. }
  547. return NULL;
  548. }
  549. //+--------------------------------------------------------------------
  550. //
  551. // Function: AccessAllowed
  552. //
  553. //---------------------------------------------------------------------
  554. BOOL
  555. AccessAllowed(BSTR bstrUrl, IUnknown * pUnkSite)
  556. {
  557. BOOL fAccessAllowed = FALSE;
  558. HRESULT hr;
  559. CComPtr<IBindHost> pBindHost;
  560. CComPtr<IMoniker> pMoniker;
  561. LPTSTR pchUrl = NULL;
  562. BYTE abSID1[MAX_SIZE_SECURITY_ID];
  563. BYTE abSID2[MAX_SIZE_SECURITY_ID];
  564. DWORD cbSID1 = ARRAY_SIZE(abSID1);
  565. DWORD cbSID2 = ARRAY_SIZE(abSID2);
  566. CComPtr<IInternetSecurityManager> pSecurityManager;
  567. CComPtr<IInternetHostSecurityManager> pHostSecurityManager;
  568. CComQIPtr<IServiceProvider, &IID_IServiceProvider> pServiceProvider(pUnkSite);
  569. if (!pServiceProvider)
  570. goto Cleanup;
  571. //
  572. // expand url
  573. //
  574. hr = pServiceProvider->QueryService(SID_IBindHost, IID_IBindHost, (void**)&pBindHost);
  575. if (hr)
  576. goto Cleanup;
  577. hr = pBindHost->CreateMoniker(bstrUrl, NULL, &pMoniker, NULL);
  578. if (hr)
  579. goto Cleanup;
  580. hr = pMoniker->GetDisplayName(NULL, NULL, &pchUrl);
  581. if (hr)
  582. goto Cleanup;
  583. //
  584. // get security id of the url
  585. //
  586. hr = CoInternetCreateSecurityManager(NULL, &pSecurityManager, 0);
  587. if (hr)
  588. goto Cleanup;
  589. hr = pSecurityManager->GetSecurityId(pchUrl, abSID1, &cbSID1, NULL);
  590. if (hr)
  591. goto Cleanup;
  592. //
  593. // get security id of the document
  594. //
  595. hr = pServiceProvider->QueryService(
  596. IID_IInternetHostSecurityManager, IID_IInternetHostSecurityManager, (void**)&pHostSecurityManager);
  597. if (hr)
  598. goto Cleanup;
  599. hr = pHostSecurityManager->GetSecurityId(abSID2, &cbSID2, NULL);
  600. //
  601. // the security check itself
  602. //
  603. fAccessAllowed = (cbSID1 == cbSID2 && (0 == memcmp(abSID1, abSID2, cbSID1)));
  604. Cleanup:
  605. if (pchUrl)
  606. CoTaskMemFree(pchUrl);
  607. return fAccessAllowed;
  608. }
  609. //+------------------------------------------------------------------------
  610. //
  611. // CDataObject : Member function implmentations
  612. //
  613. //-------------------------------------------------------------------------
  614. HRESULT
  615. CDataObject::Set (BSTR bstrValue)
  616. {
  617. VariantClear(&_varValue);
  618. _fDirty = TRUE;
  619. V_VT(&_varValue) = VT_BSTR;
  620. if (!bstrValue)
  621. {
  622. V_BSTR(&_varValue) = NULL;
  623. return S_OK;
  624. }
  625. else
  626. {
  627. V_BSTR(&_varValue) = SysAllocStringLen(bstrValue, SysStringLen(bstrValue));
  628. return (V_BSTR(&_varValue)) ? S_OK : E_OUTOFMEMORY;
  629. }
  630. }
  631. HRESULT
  632. CDataObject::Set (VARIANT_BOOL vBool)
  633. {
  634. VariantClear(&_varValue);
  635. _fDirty = TRUE;
  636. V_VT(&_varValue) = VT_BOOL;
  637. V_BOOL(&_varValue) = vBool;
  638. return S_OK;
  639. }
  640. HRESULT
  641. CDataObject::Set(IDispatch * pDisp)
  642. {
  643. VariantClear(&_varValue);
  644. _fDirty = TRUE;
  645. V_VT(&_varValue) = VT_DISPATCH;
  646. V_DISPATCH(&_varValue) = pDisp;
  647. if (pDisp)
  648. pDisp->AddRef();
  649. return S_OK;
  650. }
  651. HRESULT
  652. CDataObject::GetAsBSTR (BSTR * pbstr)
  653. {
  654. HRESULT hr = S_OK;
  655. if (!pbstr)
  656. {
  657. hr = E_POINTER;
  658. goto Cleanup;
  659. }
  660. *pbstr = NULL;
  661. if (V_VT(&_varValue) == VT_BSTR)
  662. {
  663. *pbstr = SysAllocStringLen(V_BSTR(&_varValue),
  664. SysStringLen(V_BSTR(&_varValue)));
  665. if (!*pbstr)
  666. hr = E_OUTOFMEMORY;
  667. }
  668. Cleanup:
  669. return hr;
  670. };
  671. HRESULT
  672. CDataObject::GetAsBOOL (VARIANT_BOOL * pVB)
  673. {
  674. HRESULT hr = S_OK;
  675. if (!pVB)
  676. {
  677. hr = E_POINTER;
  678. goto Cleanup;
  679. }
  680. if (V_VT(&_varValue) != VT_BOOL)
  681. {
  682. *pVB = VB_FALSE;
  683. hr = S_FALSE;
  684. }
  685. else
  686. {
  687. *pVB = V_BOOL(&_varValue);
  688. }
  689. Cleanup:
  690. return hr;
  691. };
  692. HRESULT
  693. CDataObject::GetAsDispatch(IDispatch ** ppDisp)
  694. {
  695. HRESULT hr = S_OK;
  696. if (!ppDisp)
  697. {
  698. hr = E_POINTER;
  699. goto Cleanup;
  700. }
  701. *ppDisp = NULL;
  702. if (V_VT(&_varValue)!= VT_DISPATCH)
  703. {
  704. hr = S_FALSE;
  705. }
  706. else
  707. {
  708. *ppDisp = V_DISPATCH(&_varValue);
  709. if (*ppDisp)
  710. (*ppDisp)->AddRef();
  711. }
  712. Cleanup:
  713. return hr;
  714. }
  715. /////////////////////////////////////////////////////////////////////////////
  716. //
  717. // Helper Class: CContextAccess
  718. // access to behavior site, element and style
  719. //
  720. /////////////////////////////////////////////////////////////////////////////
  721. /////////////////////////////////////////////////////////////////////////////
  722. CContextAccess::CContextAccess(IElementBehaviorSite * pSite)
  723. {
  724. memset (this, 0, sizeof(*this));
  725. _pSite = pSite;
  726. _pSite->AddRef();
  727. }
  728. CContextAccess::CContextAccess(IHTMLElement * pElement)
  729. {
  730. memset (this, 0, sizeof(*this));
  731. _dwAccess = CA_ELEM;
  732. _pElem = pElement;
  733. _pElem->AddRef();
  734. }
  735. /////////////////////////////////////////////////////////////////////////////
  736. CContextAccess::~CContextAccess()
  737. {
  738. DWORD dw;
  739. ReleaseInterface (_pSite);
  740. // the point of this loop is to avoid doing as many ReleaseInterface-s as we have possible values in CONTEXT_ACCESS enum.
  741. // instead, we do as many ReleaseInterface-s as number of bits actually set in dwAccess.
  742. while (_dwAccess)
  743. {
  744. dw = (_dwAccess - 1) & _dwAccess;
  745. switch (_dwAccess - dw)
  746. {
  747. case CA_SITEOM: _pSiteOM->Release(); break;
  748. case CA_SITERENDER: _pSiteRender->Release(); break;
  749. case CA_ELEM: _pElem->Release(); break;
  750. case CA_ELEM2: _pElem2->Release(); break;
  751. case CA_ELEM3: _pElem3->Release(); break;
  752. case CA_STYLE: _pStyle->Release(); break;
  753. case CA_STYLE2: _pStyle2->Release(); break;
  754. case CA_STYLE3: _pStyle3->Release(); break;
  755. case CA_DEFAULTS: _pDefaults->Release(); break;
  756. case CA_DEFSTYLE: _pDefStyle->Release(); break;
  757. case CA_DEFSTYLE2: _pDefStyle2->Release(); break;
  758. case CA_DEFSTYLE3: _pDefStyle3->Release(); break;
  759. default: Assert (FALSE && "invalid _dwAccess"); break;
  760. }
  761. _dwAccess = dw;
  762. }
  763. }
  764. /////////////////////////////////////////////////////////////////////////////
  765. HRESULT
  766. CContextAccess::Open(DWORD dwAccess)
  767. {
  768. HRESULT hr = S_OK;
  769. DWORD dw, dw2, dw3;
  770. // NOTE order of these ifs is important
  771. // STYLE2 or STYLE3 require us to get STYLE
  772. if (dwAccess & (CA_STYLE2 | CA_STYLE3))
  773. dwAccess |= CA_STYLE;
  774. // ELEM2, ELEM3, or CA_STYLE require us to get ELEM
  775. if (dwAccess & (CA_ELEM2 | CA_ELEM3 | CA_STYLE))
  776. dwAccess |= CA_ELEM;
  777. // DEFSTYLE2 or DEFSTYLE3 require us to get STYLE
  778. if (dwAccess & (CA_DEFSTYLE2 | CA_DEFSTYLE3))
  779. dwAccess |= CA_DEFSTYLE;
  780. // any DEFSTYLE require us to get PELEM
  781. if (dwAccess & (CA_DEFSTYLE))
  782. dwAccess |= CA_DEFAULTS;
  783. // PELEM requires us to get SITEOM
  784. if (dwAccess & (CA_DEFAULTS))
  785. dwAccess |= CA_SITEOM;
  786. // the point of this loop is to avoid doing as many ifs as we have possible values in CONTEXT_ACCESS enum.
  787. // instead, we do as many ifs as number of bits actually set in dwAccess.
  788. dw = dwAccess;
  789. while (dw)
  790. {
  791. dw2 = (dw - 1) & dw;
  792. dw3 = dw - dw2;
  793. if (0 == (dw3 & _dwAccess))
  794. {
  795. switch (dw3)
  796. {
  797. case CA_SITEOM:
  798. Assert (_pSite && !_pSiteOM);
  799. hr = _pSite->QueryInterface(IID_IElementBehaviorSiteOM2, (void**)&_pSiteOM);
  800. if (hr)
  801. goto Cleanup;
  802. break;
  803. case CA_SITERENDER:
  804. Assert (_pSite && !_pSiteRender);
  805. hr = _pSite->QueryInterface(IID_IElementBehaviorSiteRender, (void**)&_pSiteRender);
  806. if (hr)
  807. goto Cleanup;
  808. break;
  809. case CA_ELEM:
  810. Assert (_pSite && !_pElem);
  811. hr = _pSite->GetElement(&_pElem);
  812. if (hr)
  813. goto Cleanup;
  814. break;
  815. case CA_ELEM2:
  816. Assert (_pElem && !_pElem2);
  817. hr = _pElem->QueryInterface(IID_IHTMLElement2, (void**)&_pElem2);
  818. if (hr)
  819. goto Cleanup;
  820. break;
  821. case CA_ELEM3:
  822. Assert (_pElem && !_pElem3);
  823. hr = _pElem->QueryInterface(IID_IHTMLElement3, (void**)&_pElem3);
  824. if (hr)
  825. goto Cleanup;
  826. break;
  827. case CA_STYLE:
  828. Assert (_pElem && !_pStyle);
  829. hr = _pElem->get_style(&_pStyle);
  830. if (hr)
  831. goto Cleanup;
  832. break;
  833. case CA_STYLE2:
  834. Assert (_pStyle && !_pStyle2);
  835. hr = _pStyle->QueryInterface(IID_IHTMLStyle2, (void**)&_pStyle2);
  836. if (hr)
  837. goto Cleanup;
  838. break;
  839. case CA_STYLE3:
  840. Assert (_pStyle && !_pStyle3);
  841. hr = _pStyle->QueryInterface(IID_IHTMLStyle3, (void**)&_pStyle3);
  842. if (hr)
  843. goto Cleanup;
  844. break;
  845. case CA_DEFAULTS:
  846. Assert (_pSiteOM && !_pDefaults);
  847. hr = _pSiteOM->GetDefaults(&_pDefaults);
  848. if (hr)
  849. goto Cleanup;
  850. break;
  851. case CA_DEFSTYLE:
  852. Assert (_pDefaults && !_pDefStyle);
  853. hr = _pDefaults->get_style(&_pDefStyle);
  854. if (hr)
  855. goto Cleanup;
  856. break;
  857. case CA_DEFSTYLE2:
  858. Assert (_pDefStyle && !_pDefStyle2);
  859. hr = _pDefStyle->QueryInterface(IID_IHTMLStyle2, (void**)&_pDefStyle2);
  860. if (hr)
  861. goto Cleanup;
  862. break;
  863. case CA_DEFSTYLE3:
  864. Assert (_pDefStyle && !_pDefStyle3);
  865. hr = _pDefStyle->QueryInterface(IID_IHTMLStyle3, (void**)&_pDefStyle3);
  866. if (hr)
  867. goto Cleanup;
  868. break;
  869. default:
  870. Assert (FALSE && "invalid dwAccess");
  871. break;
  872. }
  873. }
  874. dw = dw2;
  875. }
  876. _dwAccess |= dwAccess;
  877. Cleanup:
  878. return hr;
  879. }
  880. /////////////////////////////////////////////////////////////////////////////
  881. #if DBG == 1
  882. HRESULT
  883. CContextAccess::DbgTest(IElementBehaviorSite * pSite)
  884. {
  885. HRESULT hr;
  886. // CA_NONE
  887. {
  888. CContextAccess a(pSite);
  889. hr = a.Open(CA_NONE);
  890. if (hr)
  891. goto Cleanup;
  892. }
  893. // CA_ELEM
  894. {
  895. CContextAccess a(pSite);
  896. hr = a.Open(CA_ELEM);
  897. if (hr)
  898. goto Cleanup;
  899. a.Elem()->AddRef();
  900. a.Elem()->Release();
  901. }
  902. // CA_ELEM2
  903. {
  904. CContextAccess a(pSite);
  905. hr = a.Open(CA_ELEM2);
  906. if (hr)
  907. goto Cleanup;
  908. a.Elem2()->AddRef();
  909. a.Elem2()->Release();
  910. }
  911. // CA_ELEM3
  912. {
  913. CContextAccess a(pSite);
  914. hr = a.Open(CA_ELEM3);
  915. if (hr)
  916. goto Cleanup;
  917. a.Elem3()->AddRef();
  918. a.Elem3()->Release();
  919. }
  920. // CA_STYLE
  921. {
  922. CContextAccess a(pSite);
  923. hr = a.Open(CA_STYLE);
  924. if (hr)
  925. goto Cleanup;
  926. a.Style()->AddRef();
  927. a.Style()->Release();
  928. }
  929. // CA_STYLE2
  930. {
  931. CContextAccess a(pSite);
  932. hr = a.Open(CA_STYLE2);
  933. if (hr)
  934. goto Cleanup;
  935. a.Style2()->AddRef();
  936. a.Style2()->Release();
  937. }
  938. // CA_STYLE3
  939. {
  940. CContextAccess a(pSite);
  941. hr = a.Open(CA_STYLE3);
  942. if (hr)
  943. goto Cleanup;
  944. a.Style3()->AddRef();
  945. a.Style3()->Release();
  946. }
  947. // CA_DEFSTYLE
  948. {
  949. CContextAccess a(pSite);
  950. hr = a.Open(CA_DEFSTYLE);
  951. if (hr)
  952. goto Cleanup;
  953. a.DefStyle()->AddRef();
  954. a.DefStyle()->Release();
  955. }
  956. // CA_DEFSTYLE2
  957. {
  958. CContextAccess a(pSite);
  959. hr = a.Open(CA_DEFSTYLE2);
  960. if (hr)
  961. goto Cleanup;
  962. a.DefStyle2()->AddRef();
  963. a.DefStyle2()->Release();
  964. }
  965. // CA_DEFSTYLE3
  966. {
  967. CContextAccess a(pSite);
  968. hr = a.Open(CA_DEFSTYLE3);
  969. if (hr)
  970. goto Cleanup;
  971. a.DefStyle3()->AddRef();
  972. a.DefStyle3()->Release();
  973. }
  974. // CA_SITEOM
  975. {
  976. CContextAccess a(pSite);
  977. hr = a.Open(CA_SITEOM);
  978. if (hr)
  979. goto Cleanup;
  980. a.SiteOM()->AddRef();
  981. a.SiteOM()->Release();
  982. }
  983. // sequencing of Opens
  984. {
  985. CContextAccess a(pSite);
  986. hr = a.Open(CA_SITEOM);
  987. if (hr)
  988. goto Cleanup;
  989. a.SiteOM()->AddRef();
  990. a.SiteOM()->Release();
  991. hr = a.Open(CA_ELEM);
  992. if (hr)
  993. goto Cleanup;
  994. a.Elem()->AddRef();
  995. a.Elem()->Release();
  996. hr = a.Open(CA_DEFSTYLE3);
  997. if (hr)
  998. goto Cleanup;
  999. a.DefStyle3()->AddRef();
  1000. a.DefStyle3()->Release();
  1001. }
  1002. Cleanup:
  1003. return hr;
  1004. }
  1005. #endif
  1006. /////////////////////////////////////////////////////////////////////////////
  1007. //
  1008. // Helper Class: CEventObjectAccess
  1009. // access to event object
  1010. //
  1011. /////////////////////////////////////////////////////////////////////////////
  1012. ///////////////////////////////////////////////////////////////////////////////
  1013. CEventObjectAccess::CEventObjectAccess(DISPPARAMS * pDispParams)
  1014. {
  1015. memset (this, 0, sizeof(*this));
  1016. _pDispParams = pDispParams;
  1017. }
  1018. ///////////////////////////////////////////////////////////////////////////////
  1019. CEventObjectAccess::~CEventObjectAccess()
  1020. {
  1021. ReleaseInterface (_pEventObj);
  1022. ReleaseInterface (_pEventObj2);
  1023. }
  1024. ///////////////////////////////////////////////////////////////////////////////
  1025. HRESULT
  1026. CEventObjectAccess::Open(DWORD dwAccess)
  1027. {
  1028. HRESULT hr = S_OK;
  1029. VARIANT * pvarArg;
  1030. Assert (_pDispParams);
  1031. if (!_pDispParams ||
  1032. !_pDispParams->rgvarg ||
  1033. _pDispParams->cArgs != 1)
  1034. {
  1035. hr = E_INVALIDARG;
  1036. goto Cleanup;
  1037. }
  1038. pvarArg = &_pDispParams->rgvarg[0];
  1039. if (!V_UNKNOWN(pvarArg) ||
  1040. (VT_DISPATCH != V_VT(pvarArg) &&
  1041. VT_UNKNOWN != V_VT(pvarArg)))
  1042. {
  1043. hr = E_INVALIDARG;
  1044. goto Cleanup;
  1045. }
  1046. if (0 != (dwAccess & EOA_EVENTOBJ) &&
  1047. !_pEventObj)
  1048. {
  1049. hr = V_UNKNOWN(pvarArg)->QueryInterface(IID_IHTMLEventObj, (void **)&_pEventObj);
  1050. if (hr)
  1051. goto Cleanup;
  1052. }
  1053. if (dwAccess & EOA_EVENTOBJ2 &&
  1054. !_pEventObj2)
  1055. {
  1056. hr = V_UNKNOWN(pvarArg)->QueryInterface(IID_IHTMLEventObj2, (void **)&_pEventObj2);
  1057. if (hr)
  1058. goto Cleanup;
  1059. }
  1060. Cleanup:
  1061. return hr;
  1062. }
  1063. HRESULT
  1064. CEventObjectAccess::GetScreenCoordinates(POINT * ppt)
  1065. {
  1066. HRESULT hr = S_OK;
  1067. if (!_fEventPropertiesInitialized)
  1068. {
  1069. hr = InitializeEventProperties();
  1070. if (hr)
  1071. goto Cleanup;
  1072. }
  1073. *ppt = _EventProperties.ptScreen;
  1074. Cleanup:
  1075. return hr;
  1076. }
  1077. HRESULT
  1078. CEventObjectAccess::GetWindowCoordinates(POINT * ppt)
  1079. {
  1080. HRESULT hr = S_OK;
  1081. if (!_fEventPropertiesInitialized)
  1082. {
  1083. hr = InitializeEventProperties();
  1084. if (hr)
  1085. goto Cleanup;
  1086. }
  1087. *ppt = _EventProperties.ptClient;
  1088. Cleanup:
  1089. return hr;
  1090. }
  1091. HRESULT
  1092. CEventObjectAccess::GetParentCoordinates(POINT * ppt)
  1093. {
  1094. HRESULT hr = S_OK;
  1095. if (!_fEventPropertiesInitialized)
  1096. {
  1097. hr = InitializeEventProperties();
  1098. if (hr)
  1099. goto Cleanup;
  1100. }
  1101. *ppt = _EventProperties.ptElem;
  1102. Cleanup:
  1103. return hr;
  1104. }
  1105. HRESULT
  1106. CEventObjectAccess::GetKeyCode(long * pl)
  1107. {
  1108. HRESULT hr = S_OK;
  1109. if (!_fEventPropertiesInitialized)
  1110. {
  1111. hr = InitializeEventProperties();
  1112. if (hr)
  1113. goto Cleanup;
  1114. }
  1115. *pl = _EventProperties.lKey;
  1116. Cleanup:
  1117. return hr;
  1118. }
  1119. HRESULT
  1120. CEventObjectAccess::GetMouseButtons(long * pl)
  1121. {
  1122. HRESULT hr = S_OK;
  1123. if (!_fEventPropertiesInitialized)
  1124. {
  1125. hr = InitializeEventProperties();
  1126. if (hr)
  1127. goto Cleanup;
  1128. }
  1129. *pl = _EventProperties.lMouseButtons;
  1130. Cleanup:
  1131. return hr;
  1132. }
  1133. HRESULT
  1134. CEventObjectAccess::GetKeyboardStatus(long * pl)
  1135. {
  1136. HRESULT hr = S_OK;
  1137. if (!_fEventPropertiesInitialized)
  1138. {
  1139. hr = InitializeEventProperties();
  1140. if (hr)
  1141. goto Cleanup;
  1142. }
  1143. *pl = _EventProperties.lKeys;
  1144. Cleanup:
  1145. return hr;
  1146. }
  1147. HRESULT
  1148. CEventObjectAccess::InitializeEventProperties()
  1149. {
  1150. HRESULT hr = S_OK;
  1151. VARIANT_BOOL b;
  1152. BOOL fAltKey = FALSE;
  1153. BOOL fCtrlKey = FALSE;
  1154. BOOL fShiftKey = FALSE;
  1155. BOOL fLeft = FALSE;
  1156. BOOL fRight = FALSE;
  1157. BOOL fMiddle = FALSE;
  1158. long lMouseButtons;
  1159. if (!_pEventObj)
  1160. {
  1161. hr = Open(EOA_EVENTOBJ);
  1162. if (hr)
  1163. goto Cleanup;
  1164. }
  1165. // KeyboardStatus
  1166. hr = _pEventObj->get_altKey(&b);
  1167. if (hr)
  1168. goto Cleanup;
  1169. fAltKey = (b == VARIANT_TRUE);
  1170. hr = _pEventObj->get_ctrlKey(&b);
  1171. if (hr)
  1172. goto Cleanup;
  1173. fCtrlKey = (b == VARIANT_TRUE);
  1174. hr = _pEventObj->get_shiftKey(&b);
  1175. if (hr)
  1176. goto Cleanup;
  1177. fShiftKey = (b == VARIANT_TRUE);
  1178. _EventProperties.lKeys = (fAltKey ? EVENT_ALTKEY : 0) | (fCtrlKey ? EVENT_CTRLKEY : 0) | (fShiftKey ? EVENT_SHIFTKEY : 0);
  1179. // MouseButtons
  1180. hr = _pEventObj->get_button(&lMouseButtons);
  1181. if (hr)
  1182. goto Cleanup;
  1183. fLeft = (lMouseButtons == 1) || (lMouseButtons == 3) || (lMouseButtons == 5) || (lMouseButtons == 7);
  1184. fRight = (lMouseButtons == 2) || (lMouseButtons == 3) || (lMouseButtons == 6) || (lMouseButtons == 7);
  1185. fMiddle = (lMouseButtons == 4) || (lMouseButtons == 5) || (lMouseButtons == 6) || (lMouseButtons == 7);
  1186. _EventProperties.lMouseButtons = ( fLeft ? EVENT_LEFTBUTTON : 0)
  1187. | (fRight ? EVENT_RIGHTBUTTON : 0)
  1188. | (fMiddle ? EVENT_MIDDLEBUTTON : 0);
  1189. // KeyCode
  1190. hr = _pEventObj->get_keyCode(&_EventProperties.lKey);
  1191. if (hr)
  1192. goto Cleanup;
  1193. // ParentCoordinates
  1194. hr = _pEventObj->get_x(&_EventProperties.ptElem.x);
  1195. if (hr)
  1196. goto Cleanup;
  1197. hr = _pEventObj->get_y(&_EventProperties.ptElem.y);
  1198. if (hr)
  1199. goto Cleanup;
  1200. // WindowCoordinates
  1201. hr = _pEventObj->get_clientX(&_EventProperties.ptClient.x);
  1202. if (hr)
  1203. goto Cleanup;
  1204. hr = _pEventObj->get_clientY(&_EventProperties.ptClient.y);
  1205. if (hr)
  1206. goto Cleanup;
  1207. // ScreenCoordinates
  1208. hr = _pEventObj->get_screenX(&_EventProperties.ptScreen.x);
  1209. if (hr)
  1210. goto Cleanup;
  1211. hr = _pEventObj->get_screenY(&_EventProperties.ptScreen.y);
  1212. if (hr)
  1213. goto Cleanup;
  1214. _fEventPropertiesInitialized = TRUE;
  1215. Cleanup:
  1216. return hr;
  1217. }
  1218. /////////////////////////////////////////////////////////////////////////////
  1219. //
  1220. // Misc helpers
  1221. //
  1222. /////////////////////////////////////////////////////////////////////////////
  1223. void *
  1224. MemAllocClear(size_t cb)
  1225. {
  1226. void * pv = malloc(cb);
  1227. if (pv)
  1228. {
  1229. memset (pv, 0, cb);
  1230. }
  1231. return pv;
  1232. }
  1233. HRESULT
  1234. LoadLibrary(char *achLibraryName, HINSTANCE *hInst)
  1235. {
  1236. DWORD dwError;
  1237. Assert(achLibraryName);
  1238. Assert(hInst);
  1239. *hInst = NULL;
  1240. // Try to load the library using the normal mechanism.
  1241. *hInst = ::LoadLibraryA(achLibraryName);
  1242. #ifdef WIN16
  1243. if ( (UINT) *hInst < 32 )
  1244. goto Error;
  1245. #endif
  1246. #if !defined(WIN16) && !defined(WINCE)
  1247. // If that failed because the module was not be found,
  1248. // then try to find the module in the directory we were
  1249. // loaded from.
  1250. if (!*hInst)
  1251. {
  1252. dwError = ::GetLastError();
  1253. if ( dwError == ERROR_MOD_NOT_FOUND
  1254. || dwError == ERROR_DLL_NOT_FOUND)
  1255. {
  1256. char achBuf1[MAX_PATH];
  1257. char achBuf2[MAX_PATH];
  1258. char *pch;
  1259. // Get path name of this module.
  1260. if (::GetModuleFileNameA(NULL, achBuf1, ARRAY_SIZE(achBuf1)) == 0)
  1261. goto Error;
  1262. // Find where the file name starts in the module path.
  1263. if (::GetFullPathNameA(achBuf1, ARRAY_SIZE(achBuf2), achBuf2, &pch) == 0)
  1264. goto Error;
  1265. // Chop off the file name to get a directory name.
  1266. *pch = 0;
  1267. // See if there's a dll with the given name in the directory.
  1268. if (::SearchPathA(
  1269. achBuf2,
  1270. achLibraryName,
  1271. NULL,
  1272. ARRAY_SIZE(achBuf1),
  1273. achBuf1,
  1274. NULL) != 0)
  1275. {
  1276. // Yes, there's a dll. Load it.
  1277. *hInst = ::LoadLibraryExA(
  1278. achBuf1,
  1279. NULL,
  1280. LOAD_WITH_ALTERED_SEARCH_PATH);
  1281. }
  1282. }
  1283. }
  1284. #endif // !defined(WIN16) && !defined(WINCE)
  1285. if (!*hInst)
  1286. {
  1287. goto Error;
  1288. }
  1289. return S_OK;
  1290. Error:
  1291. dwError = GetLastError();
  1292. return dwError ? HRESULT_FROM_WIN32(dwError) : E_FAIL;
  1293. }
  1294. //+----------------------------------------------------------------------------
  1295. //
  1296. // Member : AccessAllowed
  1297. //
  1298. // Synopsis : Internal helper. this function is part of the behavior security
  1299. // model for this tag. We only allow layout rects to be trusted if they're
  1300. // within a trusted dialog.
  1301. //
  1302. //-----------------------------------------------------------------------------
  1303. BOOL
  1304. TemplateAccessAllowed(IElementBehaviorSite *pISite)
  1305. {
  1306. #ifdef TEMPLATE_TESTING
  1307. return TRUE;
  1308. #else
  1309. HRESULT hr;
  1310. IHTMLElement * pElem = NULL;
  1311. IDispatch * pDoc = NULL;
  1312. IOleCommandTarget * pioct = NULL;
  1313. VARIANT varRet;
  1314. MSOCMD msocmd;
  1315. if (!pISite)
  1316. return FALSE;
  1317. VariantInit(&varRet);
  1318. msocmd.cmdID = IDM_ISTRUSTEDDLG;
  1319. msocmd.cmdf = 0;
  1320. hr = pISite->GetElement(&pElem);
  1321. if (FAILED(hr))
  1322. goto Cleanup;
  1323. hr = pElem->get_document(&pDoc);
  1324. if (FAILED(hr))
  1325. goto Cleanup;
  1326. hr = pDoc->QueryInterface(IID_IOleCommandTarget, (void**)&pioct);
  1327. if (hr)
  1328. goto Cleanup;
  1329. hr = pioct->Exec(&CGID_MSHTML, IDM_GETPRINTTEMPLATE, NULL, NULL, &varRet);
  1330. Cleanup:
  1331. ReleaseInterface(pElem);
  1332. ReleaseInterface(pDoc);
  1333. ReleaseInterface(pioct);
  1334. return (hr || V_VT(&varRet) != VT_BOOL || V_BOOL(&varRet) != VB_TRUE) ? FALSE : TRUE;
  1335. #endif
  1336. }
  1337. //------------------------------------------------------------------------------
  1338. //---------------------------------- Wrappers ----------------------------------
  1339. //------------------------------------------------------------------------------
  1340. STDAPI
  1341. SHGetFolderPathA(HWND hwnd, int csidl, HANDLE hToken, DWORD dwFlags, LPSTR pchPath)
  1342. {
  1343. HMODULE hDLL = NULL;
  1344. void * pfnSHGetFolderPath = NULL ;
  1345. if (g_fUseShell32InsteadOfSHFolder)
  1346. {
  1347. hDLL = LoadLibraryA("shell32.dll");
  1348. if (hDLL)
  1349. {
  1350. pfnSHGetFolderPath = GetProcAddress(hDLL, "SHGetFolderPathA");
  1351. if(!pfnSHGetFolderPath)
  1352. {
  1353. FreeLibrary(hDLL);
  1354. hDLL = NULL;
  1355. }
  1356. }
  1357. }
  1358. if (!hDLL)
  1359. {
  1360. hDLL = LoadLibraryA("shfolder.dll");
  1361. if (hDLL)
  1362. {
  1363. pfnSHGetFolderPath = GetProcAddress(hDLL, "SHGetFolderPathA");
  1364. if(!pfnSHGetFolderPath)
  1365. {
  1366. FreeLibrary(hDLL);
  1367. hDLL = NULL;
  1368. }
  1369. }
  1370. }
  1371. if (pfnSHGetFolderPath)
  1372. {
  1373. HRESULT hr = (*(HRESULT (STDAPICALLTYPE *)(HWND, int, HANDLE, DWORD, LPSTR))pfnSHGetFolderPath)
  1374. (hwnd, csidl, hToken, dwFlags, pchPath);
  1375. FreeLibrary(hDLL);
  1376. return hr;
  1377. }
  1378. return E_FAIL;
  1379. }