Rietveld Code Review Tool
Help | Bug tracker | Discussion group | Source code

Delta Between Two Patch Sets: src/plugin/PluginClass.cpp

Issue 4912420225024000: Issue #1234 - Convert strings associated with URL's (Closed)
Left Patch Set: Rebased Created Oct. 21, 2014, 6:26 p.m.
Right Patch Set: Created Jan. 5, 2015, 4:15 p.m.
Left:
Right:
Use n/p to move between diff chunks; N/P to move between comments.
Jump to:
Left: Side by side diff | Download
Right: Side by side diff | Download
LEFTRIGHT
1 #include "PluginStdAfx.h" 1 #include "PluginStdAfx.h"
2 2
3 #include "PluginClass.h" 3 #include "PluginClass.h"
4 #include "PluginSettings.h" 4 #include "PluginSettings.h"
5 #include "PluginSystem.h" 5 #include "PluginSystem.h"
6 #include "PluginFilter.h" 6 #include "PluginFilter.h"
7 #include "PluginMimeFilterClient.h" 7 #include "PluginMimeFilterClient.h"
8 #include "PluginClient.h" 8 #include "PluginClient.h"
9 #include "PluginClientFactory.h" 9 #include "PluginClientFactory.h"
10 #include "PluginMutex.h" 10 #include "PluginMutex.h"
(...skipping 25 matching lines...) Expand all
36 ATOM CPluginClass::s_atomPaneClass = NULL; 36 ATOM CPluginClass::s_atomPaneClass = NULL;
37 HINSTANCE CPluginClass::s_hUxtheme = NULL; 37 HINSTANCE CPluginClass::s_hUxtheme = NULL;
38 std::set<CPluginClass*> CPluginClass::s_instances; 38 std::set<CPluginClass*> CPluginClass::s_instances;
39 std::map<DWORD, CPluginClass*> CPluginClass::s_threadInstances; 39 std::map<DWORD, CPluginClass*> CPluginClass::s_threadInstances;
40 40
41 CComAutoCriticalSection CPluginClass::s_criticalSectionLocal; 41 CComAutoCriticalSection CPluginClass::s_criticalSectionLocal;
42 CComAutoCriticalSection CPluginClass::s_criticalSectionBrowser; 42 CComAutoCriticalSection CPluginClass::s_criticalSectionBrowser;
43 CComAutoCriticalSection CPluginClass::s_criticalSectionWindow; 43 CComAutoCriticalSection CPluginClass::s_criticalSectionWindow;
44 44
45 CComQIPtr<IWebBrowser2> CPluginClass::s_asyncWebBrowser2; 45 CComQIPtr<IWebBrowser2> CPluginClass::s_asyncWebBrowser2;
46 std::map<UINT,CString> CPluginClass::s_menuDomains;
47 46
48 /* 47 /*
49 * Without namespace declaration, the identifier "Rectangle" is ambiguous 48 * Without namespace declaration, the identifier "Rectangle" is ambiguous
50 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx 49 * See http://msdn.microsoft.com/en-us/library/windows/desktop/dd162898(v=vs.85) .aspx
51 */ 50 */
52 namespace AdblockPlus 51 namespace AdblockPlus
53 { 52 {
54 /** 53 /**
55 * Replacement for ATL type CRect. 54 * Replacement for ATL type CRect.
56 */ 55 */
(...skipping 145 matching lines...) Expand 10 before | Expand all | Expand 10 after
202 201
203 return browser; 202 return browser;
204 } 203 }
205 204
206 std::wstring CPluginClass::GetBrowserUrl() const 205 std::wstring CPluginClass::GetBrowserUrl() const
207 { 206 {
208 std::wstring url; 207 std::wstring url;
209 CComQIPtr<IWebBrowser2> browser = GetBrowser(); 208 CComQIPtr<IWebBrowser2> browser = GetBrowser();
210 if (browser) 209 if (browser)
211 { 210 {
212 BSTR bstrURL; 211 CComBSTR bstrURL;
213 if (SUCCEEDED(browser->get_LocationURL(&bstrURL)) && bstrURL) 212 if (SUCCEEDED(browser->get_LocationURL(&bstrURL)) && bstrURL)
214 { 213 {
215 url = std::wstring(bstrURL, SysStringLen(bstrURL)); 214 url = std::wstring(bstrURL, SysStringLen(bstrURL));
216 SysFreeString(bstrURL);
217 UnescapeUrl(url); 215 UnescapeUrl(url);
218 } 216 }
219 } 217 }
220 else 218 else
221 { 219 {
222 url = m_tab->GetDocumentUrl(); 220 url = m_tab->GetDocumentUrl();
223 } 221 }
224 return url; 222 return url;
225 } 223 }
226 224
(...skipping 154 matching lines...) Expand 10 before | Expand all | Expand 10 after
381 { 379 {
382 s_instances.erase(this); 380 s_instances.erase(this);
383 381
384 std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::GetC urrentThreadId()); 382 std::map<DWORD,CPluginClass*>::iterator it = s_threadInstances.find(::GetC urrentThreadId());
385 if (it != s_threadInstances.end()) 383 if (it != s_threadInstances.end())
386 { 384 {
387 s_threadInstances.erase(it); 385 s_threadInstances.erase(it);
388 } 386 }
389 if (s_instances.empty()) 387 if (s_instances.empty())
390 { 388 {
389 // TODO: Explicitly releasing a resource when a container becomes empty looks like a job better suited for shared_ptr
391 CPluginClientFactory::ReleaseMimeFilterClientInstance(); 390 CPluginClientFactory::ReleaseMimeFilterClientInstance();
392 } 391 }
393 } 392 }
394 s_criticalSectionLocal.Unlock(); 393 s_criticalSectionLocal.Unlock();
395 394
396 // Release browser interface 395 // Release browser interface
397 s_criticalSectionBrowser.Lock(); 396 s_criticalSectionBrowser.Lock();
398 { 397 {
399 m_webBrowser2.Release(); 398 m_webBrowser2.Release();
400 } 399 }
(...skipping 113 matching lines...) Expand 10 before | Expand all | Expand 10 after
514 } 513 }
515 } 514 }
516 else 515 else
517 { 516 {
518 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_GET_STATUSBAR, "Class ::Get statusbar state"); 517 DEBUG_ERROR_LOG(hr, PLUGIN_ERROR_UI, PLUGIN_ERROR_UI_GET_STATUSBAR, "Class ::Get statusbar state");
519 } 518 }
520 } 519 }
521 DEBUG_GENERAL("ShowStatusBar end"); 520 DEBUG_GENERAL("ShowStatusBar end");
522 } 521 }
523 522
523 /*
524 * #1163 This class is the implementation for method DISPID_BEFORENAVIGATE2 in C PluginClass::Invoke.
525 * - It validates and convertes its own arguments, rather than unifying them in the Invoke body.
526 * - It's declared void and not HRESULT, so DISPID_BEFORENAVIGATE2 can only retu rn S_OK.
527 */
524 void CPluginClass::BeforeNavigate2(DISPPARAMS* pDispParams) 528 void CPluginClass::BeforeNavigate2(DISPPARAMS* pDispParams)
525 { 529 {
526 530
527 if (pDispParams->cArgs < 7) 531 if (pDispParams->cArgs < 7)
528 { 532 {
529 return; 533 return;
530 } 534 }
531 //Register a mime filter if it's not registered yet 535 //Register a mime filter if it's not registered yet
532 if (s_mimeFilter == NULL) 536 if (s_mimeFilter == NULL)
533 { 537 {
(...skipping 49 matching lines...) Expand 10 before | Expand all | Expand 10 after
583 587
584 UpdateStatusBar(); 588 UpdateStatusBar();
585 } 589 }
586 else 590 else
587 { 591 {
588 DEBUG_NAVI(L"Navi::Begin navigation url:" + urlLegacy) 592 DEBUG_NAVI(L"Navi::Begin navigation url:" + urlLegacy)
589 m_tab->CacheFrame(url); 593 m_tab->CacheFrame(url);
590 } 594 }
591 } 595 }
592 596
597 /*
598 * #1163 implements behavior for method DISPID_WINDOWSTATECHANGED in CPluginClas s::Invoke
599 * - should validate and convert arguments in Invoke, not here
600 * - does not validate number of arguments before indexing into 'rgvarg'
601 * - does not validate type of argument before using its value
602 */
593 STDMETHODIMP CPluginClass::OnTabChanged(DISPPARAMS* pDispParams, WORD wFlags) 603 STDMETHODIMP CPluginClass::OnTabChanged(DISPPARAMS* pDispParams, WORD wFlags)
594 { 604 {
595 DEBUG_GENERAL("Tab changed"); 605 DEBUG_GENERAL("Tab changed");
596 bool newtabshown = pDispParams->rgvarg[1].intVal==3; 606 bool newtabshown = pDispParams->rgvarg[1].intVal==3;
597 if (newtabshown) 607 if (newtabshown)
598 { 608 {
599 std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find(Ge tCurrentThreadId()); 609 std::map<DWORD,CPluginClass*>::const_iterator it = s_threadInstances.find(Ge tCurrentThreadId());
600 if (it == s_threadInstances.end()) 610 if (it == s_threadInstances.end())
601 { 611 {
602 s_threadInstances[::GetCurrentThreadId()] = this; 612 s_threadInstances[::GetCurrentThreadId()] = this;
603
604
605 if (!m_isInitializedOk) 613 if (!m_isInitializedOk)
606 { 614 {
607 m_isInitializedOk = true; 615 m_isInitializedOk = true;
608 if (!InitObject(true)) 616 InitObject(true);
609 {
610 //» » » » » Unadvice();
611 }
612 UpdateStatusBar(); 617 UpdateStatusBar();
613 } 618 }
614 } 619 }
615 } 620 }
616 notificationMessage.Hide(); 621 notificationMessage.Hide();
617 DEBUG_GENERAL("Tab change end"); 622 DEBUG_GENERAL("Tab change end");
618 return VARIANT_TRUE; 623 return S_OK;
619 } 624 }
620 625
621 // This gets called whenever there's a browser event 626 // This gets called whenever there's a browser event
627 // ENTRY POINT
622 STDMETHODIMP CPluginClass::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, W ORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr) 628 STDMETHODIMP CPluginClass::Invoke(DISPID dispidMember, REFIID riid, LCID lcid, W ORD wFlags, DISPPARAMS* pDispParams, VARIANT* pvarResult, EXCEPINFO* pExcepInfo, UINT* puArgErr)
623 { 629 {
624 WCHAR tmp[256]; 630 try
625 wsprintf(tmp, L"Invoke: %d\n", dispidMember); 631 {
626 DEBUG_GENERAL(tmp); 632 WCHAR tmp[256];
627 switch (dispidMember) 633 wsprintf(tmp, L"Invoke: %d\n", dispidMember);
628 { 634 DEBUG_GENERAL(tmp);
629 635 switch (dispidMember)
630 case DISPID_WINDOWSTATECHANGED: 636 {
631 return OnTabChanged(pDispParams, wFlags); 637 case DISPID_WINDOWSTATECHANGED:
632 break; 638 {
633 case DISPID_HTMLDOCUMENTEVENTS2_ONBEFOREUPDATE: 639 // #1163 should validate and convert arguments here
634 return VARIANT_TRUE; 640 return OnTabChanged(pDispParams, wFlags);
635 break; 641 }
636 642
637 case DISPID_HTMLDOCUMENTEVENTS2_ONCLICK: 643 case DISPID_HTMLDOCUMENTEVENTS2_ONBEFOREUPDATE:
638 return VARIANT_TRUE; 644 break;
639 break; 645
640 646 case DISPID_HTMLDOCUMENTEVENTS2_ONCLICK:
641 case DISPID_EVMETH_ONLOAD: 647 break;
642 DEBUG_NAVI("Navi::OnLoad") 648
643 return VARIANT_TRUE; 649 case DISPID_EVMETH_ONLOAD:
644 break; 650 DEBUG_NAVI("Navi::OnLoad")
645 651 break;
646 case DISPID_EVMETH_ONCHANGE: 652
647 return VARIANT_TRUE; 653 case DISPID_EVMETH_ONCHANGE:
648 654 break;
649 case DISPID_EVMETH_ONMOUSEDOWN: 655
650 return VARIANT_TRUE; 656 case DISPID_EVMETH_ONMOUSEDOWN:
651 657 break;
652 case DISPID_EVMETH_ONMOUSEENTER: 658
653 return VARIANT_TRUE; 659 case DISPID_EVMETH_ONMOUSEENTER:
654 660 break;
655 case DISPID_IHTMLIMGELEMENT_START: 661
656 return VARIANT_TRUE; 662 case DISPID_IHTMLIMGELEMENT_START:
657 663 break;
658 case STDDISPID_XOBJ_ERRORUPDATE: 664
659 return VARIANT_TRUE; 665 case STDDISPID_XOBJ_ERRORUPDATE:
660 666 break;
661 case STDDISPID_XOBJ_ONPROPERTYCHANGE: 667
662 return VARIANT_TRUE; 668 case STDDISPID_XOBJ_ONPROPERTYCHANGE:
663 669 break;
664 case DISPID_READYSTATECHANGE: 670
665 DEBUG_NAVI("Navi::ReadyStateChange") 671 case DISPID_READYSTATECHANGE:
666 return VARIANT_TRUE; 672 DEBUG_NAVI("Navi::ReadyStateChange");
667 673 break;
668 case DISPID_BEFORENAVIGATE: 674
669 DEBUG_NAVI("Navi::BeforeNavigate") 675 case DISPID_BEFORENAVIGATE:
670 return VARIANT_TRUE; 676 DEBUG_NAVI("Navi::BeforeNavigate");
671 case DISPID_COMMANDSTATECHANGE: 677 break;
672 if (m_hPaneWnd == NULL) 678
673 { 679 case DISPID_COMMANDSTATECHANGE:
674 CreateStatusBarPane(); 680 if (m_hPaneWnd == NULL)
675 } 681 {
676 else 682 CreateStatusBarPane();
677 { 683 }
678 if (CPluginClient::GetInstance()->GetIEVersion() > 6) 684 else
679 { 685 {
680 RECT rect; 686 if (CPluginClient::GetInstance()->GetIEVersion() > 6)
681 BOOL rectRes = GetClientRect(m_hStatusBarWnd, &rect); 687 {
682 if (rectRes == TRUE) 688 RECT rect;
683 { 689 BOOL rectRes = GetClientRect(m_hStatusBarWnd, &rect);
684 MoveWindow(m_hPaneWnd, rect.right - 200, 0, m_nPaneWidth, rect.bottom - rect.top, TRUE); 690 if (rectRes == TRUE)
685 } 691 {
686 } 692 MoveWindow(m_hPaneWnd, rect.right - 200, 0, m_nPaneWidth, rect.botto m - rect.top, TRUE);
687 } 693 }
688 break; 694 }
689 case DISPID_STATUSTEXTCHANGE: 695 }
690 break; 696 break;
691 697
692 case DISPID_BEFORENAVIGATE2: 698 case DISPID_STATUSTEXTCHANGE:
693 BeforeNavigate2(pDispParams); 699 break;
694 break; 700
695 701 case DISPID_BEFORENAVIGATE2:
696 case DISPID_DOWNLOADBEGIN: 702 {
697 { 703 // #1163 should validate and convert parameters here
698 DEBUG_NAVI("Navi::Download Begin") 704 BeforeNavigate2(pDispParams);
699 } 705 }
700 break; 706 break;
701 707
702 case DISPID_DOWNLOADCOMPLETE: 708 case DISPID_DOWNLOADBEGIN:
703 { 709 {
704 DEBUG_NAVI("Navi::Download Complete") 710 DEBUG_NAVI("Navi::Download Begin")
705 711 }
712 break;
713
714 case DISPID_DOWNLOADCOMPLETE:
715 {
716 DEBUG_NAVI("Navi::Download Complete");
706 CComQIPtr<IWebBrowser2> browser = GetBrowser(); 717 CComQIPtr<IWebBrowser2> browser = GetBrowser();
707 if (browser) 718 if (browser)
708 { 719 {
709 m_tab->OnDownloadComplete(browser); 720 m_tab->OnDownloadComplete(browser);
710 } 721 }
711 } 722 }
712 break; 723 break;
713 724
714 case DISPID_DOCUMENTCOMPLETE: 725 case DISPID_DOCUMENTCOMPLETE:
715 { 726 {
716 DEBUG_NAVI("Navi::Document Complete") 727 DEBUG_NAVI("Navi::Document Complete");
717
718 CComQIPtr<IWebBrowser2> browser = GetBrowser(); 728 CComQIPtr<IWebBrowser2> browser = GetBrowser();
719 729 if (browser && pDispParams->cArgs >= 2 && pDispParams->rgvarg[1].vt == V T_DISPATCH)
720 if (browser && pDispParams->cArgs >= 2 && pDispParams->rgvarg[1].vt == VT_ DISPATCH) 730 {
721 { 731 CComQIPtr<IWebBrowser2> pBrowser = pDispParams->rgvarg[1].pdispVal;
722 CComQIPtr<IWebBrowser2> pBrowser = pDispParams->rgvarg[1].pdispVal; 732 if (pBrowser)
723 if (pBrowser)
724 {
725 BSTR bstrUrl;
726 if (SUCCEEDED(pBrowser->get_LocationURL(&bstrUrl)) && ::SysStringLen(b strUrl) > 0)
727 { 733 {
728 std::wstring url(bstrUrl, SysStringLen(bstrUrl)); 734 CComBSTR bstrUrl;
729 SysFreeString(bstrUrl); 735 if (SUCCEEDED(pBrowser->get_LocationURL(&bstrUrl)) && bstrUrl && ::S ysStringLen(bstrUrl) > 0)
730 UnescapeUrl(url); 736 {
731 m_tab->OnDocumentComplete(browser, url, browser.IsEqualObject(pBrows er)); 737 std::wstring url = std::wstring(bstrUrl, SysStringLen(bstrUrl));
738 UnescapeUrl(url);
739 m_tab->OnDocumentComplete(browser, url, browser.IsEqualObject(pBro wser));
740 }
732 } 741 }
733 } 742 }
734 } 743 }
735 } 744 break;
736 break; 745
737 746 case DISPID_ONQUIT:
738 case DISPID_ONQUIT: 747 case DISPID_QUIT:
739 case DISPID_QUIT: 748 {
740 { 749 Unadvice();
741 Unadvice(); 750 }
742 } 751 break;
743 break; 752
744 753 default:
745 default: 754 {
746 { 755 CString did;
747 CString did; 756 did.Format(L"DispId:%u", dispidMember);
748 did.Format(L"DispId:%u", dispidMember); 757
749 758 DEBUG_NAVI(L"Navi::Default " + did)
750 DEBUG_NAVI(L"Navi::Default " + did) 759 }
751 } 760 /*
752 761 * Ordinarily a method not dispatched should return DISP_E_MEMBERNOTFOUND.
753 // do nothing 762 * As a conservative initial change, we leave it behaving as before,
754 break; 763 * which is to do nothing and return S_OK.
755 } 764 */
756 765 // do nothing
757 return VARIANT_TRUE; 766 break;
767 }
768 }
769 catch(...)
770 {
771 DEBUG_GENERAL( "Caught unknown exception in CPluginClass::Invoke" );
772 return E_FAIL;
773 }
774 return S_OK;
758 } 775 }
759 776
760 bool CPluginClass::InitObject(bool bBHO) 777 bool CPluginClass::InitObject(bool bBHO)
761 { 778 {
762 DEBUG_GENERAL("InitObject"); 779 DEBUG_GENERAL("InitObject");
763 CPluginSettings* settings = CPluginSettings::GetInstance(); 780 CPluginSettings* settings = CPluginSettings::GetInstance();
764 781
765 if (!settings->GetPluginEnabled()) 782 if (!settings->GetPluginEnabled())
766 { 783 {
767 s_mimeFilter->Unregister(); 784 s_mimeFilter->Unregister();
(...skipping 499 matching lines...) Expand 10 before | Expand all | Expand 10 after
1267 // Invalidate and redraw the control 1284 // Invalidate and redraw the control
1268 UpdateStatusBar(); 1285 UpdateStatusBar();
1269 } 1286 }
1270 1287
1271 1288
1272 bool CPluginClass::SetMenuBar(HMENU hMenu, const std::wstring& url) 1289 bool CPluginClass::SetMenuBar(HMENU hMenu, const std::wstring& url)
1273 { 1290 {
1274 DEBUG_GENERAL("SetMenuBar"); 1291 DEBUG_GENERAL("SetMenuBar");
1275 1292
1276 std::wstring ctext; 1293 std::wstring ctext;
1277
1278 s_criticalSectionLocal.Lock();
1279 {
1280 s_menuDomains.clear();
1281 }
1282 s_criticalSectionLocal.Unlock();
1283
1284 Dictionary* dictionary = Dictionary::GetInstance(); 1294 Dictionary* dictionary = Dictionary::GetInstance();
1285 1295
1286 MENUITEMINFOW fmii = {}; 1296 MENUITEMINFOW fmii = {};
1287 fmii.cbSize = sizeof(fmii); 1297 fmii.cbSize = sizeof(fmii);
1288 1298
1289 MENUITEMINFOW miiSep = {}; 1299 MENUITEMINFOW miiSep = {};
1290 miiSep.cbSize = sizeof(miiSep); 1300 miiSep.cbSize = sizeof(miiSep);
1291 miiSep.fMask = MIIM_TYPE | MIIM_FTYPE; 1301 miiSep.fMask = MIIM_TYPE | MIIM_FTYPE;
1292 miiSep.fType = MFT_SEPARATOR; 1302 miiSep.fType = MFT_SEPARATOR;
1293 1303
(...skipping 219 matching lines...) Expand 10 before | Expand all | Expand 10 after
1513 1523
1514 HICON CPluginClass::GetStatusBarIcon(const std::wstring& url) 1524 HICON CPluginClass::GetStatusBarIcon(const std::wstring& url)
1515 { 1525 {
1516 // use the disable icon as defualt, if the client doesn't exists 1526 // use the disable icon as defualt, if the client doesn't exists
1517 HICON hIcon = GetIcon(ICON_PLUGIN_DEACTIVATED); 1527 HICON hIcon = GetIcon(ICON_PLUGIN_DEACTIVATED);
1518 1528
1519 CPluginTab* tab = GetTab(::GetCurrentThreadId()); 1529 CPluginTab* tab = GetTab(::GetCurrentThreadId());
1520 if (tab) 1530 if (tab)
1521 { 1531 {
1522 CPluginClient* client = CPluginClient::GetInstance(); 1532 CPluginClient* client = CPluginClient::GetInstance();
1523 if (!CPluginSettings::GetInstance()->IsPluginEnabled()) 1533 if (CPluginSettings::GetInstance()->IsPluginEnabled())
1524 { 1534 {
1525 } 1535 if (client->IsWhitelistedUrl(url))
1526 else if (client->IsWhitelistedUrl(url)) 1536 {
1527 { 1537 hIcon = GetIcon(ICON_PLUGIN_DISABLED);
1528 hIcon = GetIcon(ICON_PLUGIN_DISABLED); 1538 }
1529 } 1539 else
1530 else 1540 {
1531 { 1541 CPluginSettings* settings = CPluginSettings::GetInstance();
1532 CPluginSettings* settings = CPluginSettings::GetInstance(); 1542 hIcon = GetIcon(ICON_PLUGIN_ENABLED);
1533 hIcon = GetIcon(ICON_PLUGIN_ENABLED); 1543 }
1534 } 1544 }
1535 } 1545 }
1536 return hIcon; 1546 return hIcon;
1537 } 1547 }
1538 1548
1539 1549
1540 LRESULT CALLBACK CPluginClass::PaneWindowProc(HWND hWnd, UINT message, WPARAM wP aram, LPARAM lParam) 1550 LRESULT CALLBACK CPluginClass::PaneWindowProc(HWND hWnd, UINT message, WPARAM wP aram, LPARAM lParam)
1541 { 1551 {
1542 // Find tab 1552 // Find tab
1543 CPluginClass *pClass = FindInstance(GetParent(hWnd)); 1553 CPluginClass *pClass = FindInstance(GetParent(hWnd));
(...skipping 320 matching lines...) Expand 10 before | Expand all | Expand 10 after
1864 } 1874 }
1865 } 1875 }
1866 } 1876 }
1867 1877
1868 hTabWnd = ::GetWindow(hTabWnd, GW_HWNDNEXT); 1878 hTabWnd = ::GetWindow(hTabWnd, GW_HWNDNEXT);
1869 } 1879 }
1870 1880
1871 return hTabWnd; 1881 return hTabWnd;
1872 1882
1873 } 1883 }
LEFTRIGHT

Powered by Google App Engine
This is Rietveld