Installing and Registering Protocol Handlers
Installing and Registering Protocol Handlers Creating a multi-threaded protocol handler involves implementing the following three interfaces:
  • ISearchProtocol to manage UrlAccessor objects.
  • IUrlAccessor to emit properties and identify appropriate filters for items in the data store.
  • IFilter to filter proprietary files or to enumerate and filter hierarchically stored files.

This topic is organized as follows:

About URLs

Windows Search uses URLs to uniquely identify items in the hierarchy of your data store. The URL that is the first node in the hierarchy is called the search root; Windows Search begins at that search root, asking the protocol handler to enumerate child links for each URL.

The typical URL structure is:

<protocol>:// [{user SID}/] <localhost>/<path>/[<ItemID>]

The <protocol> portion identifies which protocol handler to invoke for the URL. If there is a {user SID} portion, the protocol handler is invoked in the security context of that user. Otherwise, it is invoked in the security context of the system service. The <path> portion defines the hierarchy of the store, where each forward slash ('/') is a separator between folder names. The <ItemID> is a unique string identifying the child item (for example, the file name).

The Windows Search Indexer trims the final slash from URLs, so you cannot rely on the existence of a final slash to identify a directory (as opposed to an item). Your protocol handler must be able to handle this URL syntax. Ensure that the protocol name that you select to identify your data store does not conflict with current ones. We recommend this naming convention: companyName.scheme.

For more information on creating a Shell data store, see Implementing the Basic Folder Object Interfaces.

Implementing Protocol Handler Interfaces

This section discusses the interfaces that implement protocol handlers. You can implement whichever interfaces best meets your needs.

ISearchProtocol and ISearchProtocol2 Interfaces

The SearchProtocol interfaces initialize and manage your protocol handler UrlAccessor objects. The ISearchProtocol2 interface is an extension of ISearchProtocol, and includes an extra method to specify more information about the user and the item.

IUrlAccessor, IUrlAccessor2, IUrlAccessor3, and IUrlAccessor4 Interfaces

The IUrlAccessor interfaces are described in the following table.

InterfaceDescription
IUrlAccessorFor a specified URL, the IUrlAccessor interface provides access to the properties of the item that is exposed in the URL. It can also bind those properties to a protocol handler-specific filter (that is, a filter other than the one associated with the file name.
IUrlAccessor2The IUrlAccessor2 interface extends IUrlAccessor with methods to get a code page for the item's properties and its display URL, and to get the type of item in the URL (document or directory).
IUrlAccessor3The IUrlAccessor3 interface extends IUrlAccessor2 with a method to get an array of user security identifiers (SIDs), enabling the search protocol host to impersonate these users to index the item.
IUrlAccessor4The IUrlAccessor4 interface extends the functionality of the IUrlAccessor3 interface with a method that identifies whether the content of the item should be indexed.

 

The UrlAccessor object is instantiated and initialized by a SearchProtocol object. The IUrlAccessor interfaces provide access to important pieces of information through the following methods:

IProtocolHandlerSite Interface

The IProtocolHandlerSite interface is used to instantiate a filter handler (an implementation of the IFilter interface), which are hosted in an isolated process. The appropriate filter handler is obtained for a specified persistent class identifier (CLSID), document storage class, or file name extension. The benefits of asking the host process to bind to IFilter is that the host process can manage the complexity of finding the appropriate filter handler, and can control the security of invoking the handler.

Implementing Filter Handlers for Containers

If you are implementing a hierarchical protocol handler, you must implement a container IFilter component that enumerates child URLs. The enumeration process is a loop through the IFilter::GetChunk and IFilter::GetValue methods of the IFilter interface; each child URL is emitted as the value of the property.

IFilter::GetChunk returns the properties of the container. To enumerate child URLs, IFilter::GetChunk returns either of the following:

  • PKEY_Search_UrlToIndex: the URL to the item without the last modified time. IFilter::GetValue returns a PROPVARIANT containing the child URL.
  • PKEY_Search_UrlToIndexWithModificationTime: the URL and the last modified time. IFilter::GetValue returns a PROPVARIANT containing a vector of the child URL and the last modified time.

Returning PKEY_Search_UrlToIndexWithModificationTime is more efficient because the indexer can immediately determine whether the item needs to be indexed without calling the ISearchProtocol::CreateAccessor and IUrlAccessor::GetLastModified methods.

The following example code demonstrates how to return PKEY_Search_UrlToIndexWithModificationTime .

Important   THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A PARTICULAR PURPOSE.

Copyright (c) Microsoft Corporation. All rights reserved.

// Parameters are assumed to be valid

HRESULT GetPropVariantForUrlAndTime(PCWSTR pszUrl, const FILETIME &ftLastModified, PROPVARIANT **ppPropValue)
{
    *ppPropValue = NULL;

    // Allocate the propvariant pointer.
    size_t const cbAlloc = sizeof(**ppPropValue);
    *ppPropValue = (PROPVARIANT *)CoTaskMemAlloc(cbAlloc));

    HRESULT hr = *ppPropValue ? S_OK : E_OUTOFMEMORY;

    if (SUCCEEDED(hr))
    {
        PropVariantInit(*ppPropValue);  // Zero init the value

        // Now allocate enough memory for 2 nested PropVariants.
        // PKEY_Search_UrlToIndexWithModificationTime is an array of two PROPVARIANTs.
        PROPVARIANT *pVector = (PROPVARIANT *)CoTaskMemAlloc(sizeof(*pVector) * 2);
        hr = pVector ? S_OK : E_OUTOFMEMORY;

        if (SUCCEEDED(hr))
        {
            // Set the container PROPVARIANT to be a vector of two PROPVARIANTS.
            (*ppPropValue)->vt = VT_VARIANT | VT_VECTOR;
            (*ppPropValue)->capropvar.cElems = 2;
            (*ppPropValue)->capropvar.pElems = pVector;
            PWSTR pszUrlAlloc;
            hr = SHStrDup(pszUrl, &pszUrlAlloc);

            if (SUCCEEDED(hr))
            {
                // Now fill the array of PROPVARIANTS.
                // Put the pointer to the URL into the vector.
                (*ppPropValue)->capropvar.pElems[0].vt = VT_LPWSTR; 
                (*ppPropValue)->capropvar.pElems[0].pwszVal = pszUrlAlloc;

                 // Put the FILETIME into vector.
                (*ppPropValue)->capropvar.pElems[1].vt = VT_FILETIME; 
                (*ppPropValue)->capropvar.pElems[1].filetime = ftLastModified;
            }

            else
            {
                CoTaskMemFree(pVector);
            }
        }
 
        if (FAILED(hr))
        {
            CoTaskMemFree(*ppPropValue);
            *ppPropValue = NULL;
        }
    }
    return S_OK;
}

Note   A container IFilter component should always enumerate all child URLs even if the child URLs have not changed, because the indexer detects deletions through the enumeration process. If the date output in a PKEY_Search_UrlToIndexWithModificationTime indicates that the data has not changed, the indexer does not update the data for that URL.

Ensuring that Your Items are Indexed

Now that you have implemented your protocol handler, you need to specify which items your handler is registered for indexing. You can use the Catalog Manager to initiate re-indexing, and you can also use the Crawl Scope Manager (CSM) to set up default rules indicating the URLs that you want the indexer to crawl. Another option is to follow the procedure in the ReIndex sample in Windows Search SDK Samples.

The ISearchCrawlScopeManager interface provides methods that notify the search engine of containers to crawl and/or watch, and items under those containers to include or exclude when crawling or watching. In Windows 7 and later, ISearchCrawlScopeManager2 extends ISearchCrawlScopeManager with the ISearchCrawlScopeManager2::GetVersion method that gets the version, which informs clients whether the state of the CSM has changed.

You may need to stop and restart the Windows Search service to initiate re-indexing.

Search Connectors for Protocol Handlers in Windows 7

In Windows 7, searches from the Start menu or Windows Explorer include only files in indexed locations, and non-file system items such as remote data stores or protocol handler items that have a search connector. In addition to including the protocol handler items in the scope of Start menu and Shell searches, the search connector enables the Start menu to group protocol handler items together in Start menu results, so the user can click the group header and view results from only the protocol handler. Alternatively, the user can navigate to the Searches folder and search, and then open the search connector file and perform a search that includes only protocol handler items.

When a user first starts an application that registers a protocol handler, Windows Explorer generates a search connector file (.searchConnector-ms) for the protocol handler in the user's Searches folder (%userprofile%/Searches). Applications with protocol handlers can choose to disable this behavior or customize the name and description of the protocol handler search connector.

Windows Explorer controls the creation of a search connector for a protocol handler through registry key entries described in the following sections:

Note  There are no programmatic means to create a search connector for a protocol handler. They must be configured through the registry.

Disabling Protocol Handler Search Connector Creation

If your application is exposing items through a protocol handler for use in the application itself, and you do not want to expose the items through the Shell, you should set the following registry key values:

  1. Set DoNotCreateSearchConnectors=1 to disable search connector creation.
  2. Set the value to TRUE to emit the System.Shell.OmitFromView property on each item exposed by the protocol handler.

Set these values in the following registry key example. CLSID is of REG_DWORD type.

HKEY_LOCAL_MACHINE
     Software
          Microsoft
               Windows Search
                    PHSearchConnectors
                         <protocol>
                              CLSID
                                   DoNotCreateSearchConnectors

Customizing the Name and Description for a Protocol Handler Search Connector

The search connector name is used not only to identify the search connector in the Searches folder, but as the group headers for the results in Start menu searches. Hence, it is important to provide a clear name for the search connector. If a name is not provided in the registry key, by default Windows Explorer uses the name and blank description provided by IShellFolder for the protocol handler's search root. You can override the default name without having to rename the IShellFolder, through a registry key entry. Name is of the REG_SZ type.

HKEY_LOCAL_MACHINE
     Software
          Microsoft
               Windows Search
                    ProtocolHandlerLocations
                         <protocol>
                              CustomLocations
                                   <SampleLocation>
                                        Name
                                        (ProtocolHandlerLocations) = <the name used is the string returned by IShellItem::GetDisplayName(SIGDN_NORMALDISPLAY) for an item bound to the search root URL>

Although it is not as visible as the search connector name, you can also set the override the description for the search connector by providing a description, as illustrated in the following registry key example. Location is of REG_SZ type.

HKEY_LOCAL_MACHINE
     Software
          Microsoft
               Windows Search
                    ProtocolHandlerLocations
                         <protocol>
                              CustomLocations
                                   <SampleLocation>
                                        Location
                                             (ProtocolHandlerLocations) = <the name used is the string returned by IShellItem::GetDisplayName(SIGDN_NORMALDISPLAY) for an item bound to the search root URL>

For reference documentation related to these registry key entries, see IShellItem::GetDisplayName and SIGDN_NORMALDISPLAY.

Using Registry String Redirection

To ensure that the name you provide for the search connector can be localized, use a redirected string. You can include localizable strings for the name and description registry keys instead of entering the actual string into the registry. Name is of the REG_SZ type.

HKEY_LOCAL_MACHINE
     Software
          Microsoft
               Windows Search
                    ProtocolHandlerLocations
                         <protocol>
                              CustomLocations
                                   <SampleLocation>
                                        Name

Restoring a Deleted Protocol Handler Search Connector

Because search connectors are files on the user's computer, they can be mistakenly deleted. To restore all deleted protocol handler search connectors, the user can restore the default libraries. To so do, open Windows Explorer, right-click the Libraries folder, and then select Restore Default Libraries.

Restore Default Libraries

Additional Resources

Related Topics

Tags :


Page view tracker