windows - IE9 का उपयोग करते हुए एक वेबब्राउज़र नियंत्रण एम्बेड करते समय IE सेटिंग्स को ओवरराइड करना



com internet-explorer-9 (1)

मेरे पास एक अनुप्रयोग है (एमएफसी के साथ सी ++ में लिखा गया है, लेकिन मुझे नहीं लगता कि यह विशेष रूप से प्रासंगिक है) जो कुछ एचटीएमएल पेज दिखाने के उद्देश्य से इंटरनेट एक्सप्लोरर एक्टिवैक वेबब्राउसर नियंत्रण को एम्बेड करता है। एक आवश्यकता हमेशा एप्लिकेशन के फ़ॉन्ट नाम और आकार सेटिंग्स का उपयोग करने के लिए है, जैसे कि इंटरनेट एक्सपोरेर के डिफ़ॉल्ट की बजाय HTML के लिए डिफ़ॉल्ट सेटिंग।

इसे प्राप्त करने के लिए, यह अनुप्रयोग IDocHostUIHandler2 COM इंटरफ़ेस लागू करता है, जो वेबब्राउज़र नियंत्रण से गुजरता है। यह नियंत्रण के लिए GetOptionKeyPath के अनुप्रयोग के कार्यान्वयन को कॉल करने के कारण होता है, जो कि एप्लिकेशन को रजिस्ट्री स्थान को सेट करने देता है जो वेबब्राउज़र नियंत्रण से इसकी सेटिंग प्राप्त करता है सिस्टेनेन्टल के उपकरणों के साथ सशस्त्र देखने के लिए कि कुंजी का उपयोग फ़ॉन्ट नाम और आकार खोजने के लिए किया जाता है, यह मेरे लिए क्या करना है, यह करने के लिए पर्याप्त है।

हालांकि, इंटरनेट एक्सप्लोरर 9 की आशंका एक गंदी आश्चर्य के रूप में आ गई है: जिस मशीन पर मैंने IE9 स्थापित किया है, उसमें सभी मशीनों पर, वेबब्राउज़र नियंत्रण अपनी सेटिंग्स का उपयोग करता है, एप्लिकेशन से रजिस्ट्री स्थान की अनदेखी कर रहा है। डीबगर के साथ परीक्षण से पता चलता है कि वेबब्राउज़र नियंत्रण कभी भी उपलब्ध कराए गए गेटिवॉशनकेपपथ को कॉल नहीं करता है।

थोड़ा और प्रयोग दिखाता है कि IE9 वेबब्रोजर नियंत्रण समान (लेकिन समान नहीं) GetOverrideKeyPath विधि को बुला रही है: यह कथित रूप से आईई सेटिंग को ओवरराइड करने का एक तरीका प्रदान करता है, जबकि आईई की वास्तविक सेटिंग्स पर वापस गिरने पर रजिस्ट्री के संबंधित भाग में कुछ नहीं मिला । दुर्भाग्य से इसकी दो समस्याएं हैं: 1) यह काफी नहीं है जो मुझे चाहिए, और 2) आईई डिफ़ॉल्ट रजिस्ट्री सेटिंग में जाने से पहले IE9 हमेशा GetOverrideKeyPath रजिस्ट्री स्थान के अंतर्गत जांच नहीं करता है।

GetOptionKeyPath एमएसडीएन पेज को देखते हुए कुछ शिकायती समान पंक्तियों के साथ हैं, लेकिन कोई समाधान नहीं। वास्तव में GetOptionKeyPath को प्रलेखित के रूप में पूर्व-आईई 9 व्यवहार में वापस लाने के लिए वेबब्रोजर नियंत्रण को मनाने के लिए किसी को भी एक साफ रास्ता मिल गया है?

https://ffff65535.com


मैं इस समस्या को हल करने के लिए एक हैक के साथ आया हूँ, लेकिन मुझे आपको चेतावनी देना चाहिए: यह सुंदर नहीं है यदि आप आसानी से नाराज हैं तो अब पढ़ना बंद करें ...

चूंकि IE9 ने IDocHostUIHandler :: GetOptionKeyPath () विधि का उपयोग करने का कोई तरीका नहीं है, इसलिए मैंने देखा है कि आईई 9 डीएलएल ने आईई 9 सेटिंग्स को लोड करने के लिए रजिस्ट्री के प्रासंगिक हिस्सों तक कैसे पहुंचा है। यह केवल "mshtml.dll" और "iertutil.dll" के रूप में अपराधियों को प्रकट करता है, जिसमें से दोनों RegOpenKeyExW () को कॉल करते हैं।

इस योजना को तब वेब ब्रॉसर नियंत्रण शुरू करने से पहले इन डीएलएल लोड करने के लिए और उन्हें पैच करना था ताकि कॉल को मेरे कोड पर ले जाया जाए, जहां मैं dbghelp.dll का उपयोग कर खोला हुआ रजिस्ट्री कुंजी के बारे में झूठ बोल सकता हूं। तो, शुरू करने के लिए, WebBrowser नियंत्रण को प्रारंभ करने से पहले:

if (theApp.GetIEVersion() >= 9.0)
{
  HMODULE advadi = ::LoadLibrary("advapi32.dll");
  HMODULE mshtml = ::LoadLibrary("mshtml.dll");
  HookApiFunction(mshtml,advadi,"advapi32.dll","RegOpenKeyExW",(PROC)HookRegOpenKeyExW);
  HMODULE iertutil = ::LoadLibrary("iertutil.dll");
  HookApiFunction(iertutil,advadi,"advapi32.dll","RegOpenKeyExW",(PROC)HookRegOpenKeyExW);
}

और अब, कोड जो DLLs को स्कैन करने के लिए बुरे काम करता है, पता टेबल को आयात करता है, और अनुरोधित फ़ंक्शन को पैचिंग करता है (कोड का आकार नीचे रखने के लिए त्रुटि से निपटने को छोड़ दिया गया है):

void HookApiFunction(HMODULE callingDll, HMODULE calledDll, const char* calledDllName, const char* functionName, PROC newFunction)
{
  // Get the pointer to the 'real' function
  PROC realFunction = ::GetProcAddress(calledDll,functionName);

  // Get the import section of the DLL, using dbghelp.dll's ImageDirectoryEntryToData()
  ULONG sz;
  PIMAGE_IMPORT_DESCRIPTOR import = (PIMAGE_IMPORT_DESCRIPTOR)
    ImageDirectoryEntryToData(callingDll,TRUE,IMAGE_DIRECTORY_ENTRY_IMPORT,&sz);

  // Find the import section matching the named DLL
  while (import->Name)
  {
    PSTR dllName = (PSTR)((PBYTE)callingDll + import->Name);
    {
      if (stricmp(dllName,calledDllName) == 0)
       break;
    }
    import++;
  }
  if (import->Name == NULL)
    return;

  // Scan the IAT for this DLL
  PIMAGE_THUNK_DATA thunk = (PIMAGE_THUNK_DATA)((PBYTE)callingDll + import->FirstThunk);
  while (thunk->u1.Function)
  {
    PROC* function = (PROC*)&(thunk->u1.Function);
    if (*function == realFunction)
    {
      // Make the function pointer writable and hook the function
      MEMORY_BASIC_INFORMATION mbi;
      ::VirtualQuery(function,&mbi,sizeof mbi);
      if (::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,PAGE_READWRITE,&mbi.Protect))
      {
        *function = newFunction;
        DWORD protect;
        ::VirtualProtect(mbi.BaseAddress,mbi.RegionSize,mbi.Protect,&protect);
        return;
      }
    }
    thunk++;
  }

अंत में, मेरे कोड में RegOpenKeyExW () के स्थान पर कॉल करने के लिए मैंने DLL को फ़ैच किया है:

LONG WINAPI HookRegOpenKeyExW(HKEY hKey, LPCWSTR lpSubKey, DWORD ulOptions, REGSAM samDesired, PHKEY phkResult)
{
  static const wchar_t* ieKey = L"Software\\Microsoft\\Internet Explorer";

  // Never redirect any of the FeatureControl settings
  if (wcsstr(lpSubKey,L"FeatureControl") != NULL)
    return ::RegOpenKeyExW(hKey,lpSubKey,ulOptions,samDesired,phkResult);

  if (wcsnicmp(lpSubKey,ieKey,wcslen(ieKey)) == 0)
  {
    // Redirect the IE settings to our registry key
    CStringW newSubKey(m_registryPath);
    newSubKey.Append(lpSubKey+wcslen(ieKey));
    return ::RegOpenKeyExW(hKey,newSubKey,ulOptions,samDesired,phkResult);
 }
 else
   return ::RegOpenKeyExW(hKey,lpSubKey,ulOptions,samDesired,phkResult);
}

आश्चर्यजनक पर्याप्त, यह भयानक हैक वास्तव में काम करता है। लेकिन कृपया, माइक्रोसॉफ्ट, अगर आप सुन रहे हैं, तो ठीक से इसे IE10 में ठीक करें।





webbrowser-control