Заміна URL для Live search в IE

Заміна URL для Live search в IE

Одразу маленька відмазка: те, що надалі описане мені потрібно було виключно по роботі. Сам я IE не користуюсь – лише Оперою та Файрфоксом 😉

Не дивлячись на те, що сабжева задача здається вельми і вельми тривіальною насправді все не атк просто. Мається на увазі URL, по якому переходить браузер, якщо ви введети якусь маячню в Location Bar (напр. набір слів, або неіснуючий домен). Точніше велику проблему це становить для IE6. Для Internet Explorer 7 все вирішується просто – URL для закачки міняється правкою ключа реєстру:

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\SearchScopes\{0633EE93-D776-472f-A0FF-E1416B8B2E3A}\URL

Міняємо прописаний там майкрософтівський Live search на щось типу:

http://www.google.com.ua/search?hl=uk&q={searchTerms}&meta=

де {searchTerms} – макрос, на місце якого підставляється введені в рядку браузера лексеми. І все ОК. А от в IE6 такого ключа нема. І там все робиться через дупу. Саме цей романтичний шлях і буде далі описано…

Для визначення URL для підстановки в Address bar в разі, коли IE не може знайти протокол по якому потрібно працювати (ви не вказали його, а дреса не містить ніяких підказок, напр. у вигляді префікса “www.”) викликається COM-об’єкт, що реалізує інтерфейс IURLSearchHook. Цей інтерфейс має лише одну член-функцію: Translate. В комплекті з IE6 йде власна реалізація цього інтерфейсу, яка відкриває сторінку auto.search.msn.com. CLSID об’єкта, який відповідатиме за постачання URL прописано в ключі HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\URLSearchHooks. По замовучуванню використовується об’єкт з CLSID {CFBFAE00-17A6-11D0-99CB-00C04FD64497}. Для того, щоб встановити власний URL для пошуку за замовчуванням нам потрібно замінити його своєю реалізацію.

Для цього створюємо звичанйий проект ATL:

Customizing IE live search - Create ATL Project
Параметри залишаємо без змін. Далі в щойноствореному проекті через Class Wizard додаємо ATL Simple Object – клас, який і буде реалізацією інтерфейсу IURLSearchHook.

Customizing IE live search - Create ATL Simple Class
Даємо цьому класу якесь ім’я. Вкладку “Options” можна не чіпати і залишити все по дефолту.

Customizing IE live search - ATL Simple Class Wizard
Class Wizard зробив для нас практично всю брудну роботу і тепер можна, власне, дописувати необхідні дані.

Файл з описанням класу (в нашому прикладі Searcher.h) доводимо до наступного вигляду:

// Searcher.h : Declaration of the CSearcher
#pragma once
#include "resource.h" // main symbols
#include <..\PlatformSDK\include\comdef.h>
#include <shlobj.h>

// ISearcher
[ object, uuid("A548953B-21A1-490F-A189-0F9FD714BDE2"),
  dual, helpstring("ISearcher Interface"), pointer_default(unique) ]
__interface ISearcher : IDispatch { };

// CSearcher
[ coclass, threading("apartment"), vi_progid("IESearchHook.Searcher"),
  progid("IESearchHook.Searcher.1"), version(1.0),
  uuid("94D618D6-E6E7-4EE9-B1B7-24C0B2327853"), helpstring("Searcher Class") ]
class ATL_NO_VTABLE CSearcher :
  public ISearcher,
  public IURLSearchHook
  {
  public:
    CSearcher() {}
  
    DECLARE_PROTECT_FINAL_CONSTRUCT()
  
    BEGIN_COM_MAP(CSearcher)
      COM_INTERFACE_ENTRY(ISearcher)
      COM_INTERFACE_ENTRY(IDispatch)
      COM_INTERFACE_ENTRY(IURLSearchHook)
    END_COM_MAP()
  
    HRESULT FinalConstruct() { return S_OK; }
  
    void FinalRelease() {}
  
  public:
    STDMETHODIMP Translate(LPWSTR lpwszSearchURL, DWORD cchBufferSize)
      {
      LPWSTR wszURL = new WCHAR[cchBufferSize];
      ::LoadStringW(_AtlBaseModule.GetModuleInstance(), IDS_URL404, wszURL, cchBufferSize);
      wcsncat(wszURL, lpwszSearchURL, cchBufferSize);
      ZeroMemory(lpwszSearchURL, wcslen(wszURL));
      wcsncpy( lpwszSearchURL, wszURL, cchBufferSize);
      delete [] wszURL;
      return S_OK;
      }
    };

Далі створюємо ресурс в String table з ідентифікатором IDS_URL404 і змістом типу: http://www.google.com/search?q= (це пошук по гуглю) і збираємо продукт. Реєстрацію COM-об’єкта Visual Studio зробить за нас, але для того, щоб зареєструвати цю dll-бібліотеку на іншому компі потрібно буде виконати команду:

regsvr32 IESearchHook.dll

До речі, по коду ще прошу звернути увагу на рядок:

#include <..\PlatformSDK\include\comdef.h>

Справа в тому, що принаймні в Visual Studio .NET (2003) є два файли comdef.h і в одному з них не прописано GUID для IURLSearchHook. І тоді при компіляції в рядку:

 COM_INTERFACE_ENTRY(IURLSearchHook)

може видаватись помилка типу:

d:\Work\Other\IESearchHook\Searcher.h(49) : error C2787: 'IURLSearchHook' : no GUID has been associated with this object

Тому для того, щоб використовувати нормальний comdef.h пересвідчіться, що використовується саме той, який лежить в:

PATH_TO_VISUAL_STUDIO\Vc7\PlatformSDK\Include\

Ну і нарешті останній крок – це підстановка нашого COM-об’єкту замість експлорерівського. Для цього в ключі

HKEY_CURRENT_USER\Software\Microsoft\Internet Explorer\URLSearchHooks

видаляємо параметр, ім’я якого є CLSID поточного об’єкту, що видає рядок пошуку і створюємо параметр з іменем, рівним CLSID нашого об’єкту, обгонувши його в фігурні дужки. Для прикладу вище – це буде “{94D618D6-E6E7-4EE9-B1B7-24C0B2327853}”.

От і все. Запускаємо Internet Explorer і насолоджуємось пошуком в Google замість Live Search 😉 Цей спосіб випробувано для Internet Explorer версій 6 та 7. По ідеї має працювати починаючи з 4-го, але це не перевірялося.

Звісно, для реальної роботи функцію Translate треба буде дещо ускладнити, але то вже більш тривіальна справа.

За реалізацію цього завдання вчасно я мушу подякувати наявності наступних двох ресурсів:

  1. Google Answers: Change Autosearch URL in IE6. Але спосіб описаний тут не зовсім працює 😉 Одна з помилок – це якраз описаний вище прикол з comdef.h
  2. Якийсь китайський ресурс. Там добре, що була купа скрінів та багато коду і я інтуітивно здогадався в цій купі ієрогліфів в чому була лажа 🙂
Sergii Gulenok

Sergii Gulenok

View Comments