ISAPI Filter Overview

As I mentioned last chapter, ISAPI extensions and ISAPI filters are similar in structure but quite different in operation. ISAPI extensions are called by the client browser and return HTML. ISAPI filters, on the other hand, are never called directlythat is part of their utility: They can transparently make existing applications behave in a different way. For instance, if you need to implement custom authentication or logging, ISAPI filters might be your only option.

An ISAPI filter is just a DLL that exports two or three specific functions that can then be called by IIS. The filter is loaded on the server. It can be installed so that all requests for all applications on the server are monitored or only requests for a single application are monitored . The filter is loaded once when IIS is loaded and remains loaded under virtually all circumstances until IIS is stopped .

An ISAPI filter sits between the client browser and IIS, as illustrated in Figure 11-1.

click to view at full size.

Figure 11-1 The relationship between a client browser, IIS, and an ISAPI filter.

The filter will see every request that meets the criteria that you specify when you design and install the filter. One of the implications of this structure is that whatever your filter does, it must do quickly. There are several ways to ensure that an ISAPI filter does not become a roadblock to a responsive Web site:

  • Request only the notifications that you absolutely need to see. Every notification you see takes some time. Within a given notification type, you cannot select some of those notification types and not othersyour filter will get them all.
  • If you will not be processing the notification, quickly return.
  • If you need to monitor only a single application, try to have the filter installed so that it only sees requests for that one site.
  • ISAPI filters can register priorities. Use the lowest priority possible.

You will encounter challenges on the road to designing a successful ISAPI filter. One of the first is debugging the filter, which for several reasons is much more difficult than it might initially appear. First, there is often no easy way to tell whether the filter is working. Some of the filter's operations are subtle, such as changing the headers sent to the client browser. Second, building the ISAPI filter DLL and getting it installed on IIS can require starting and stopping the IIS services. Finally, while you can use modern debugging tools such as Microsoft Visual Studio to debug ISAPI filters, the task is still difficult.

Functions Exported by ISAPI Filter DLLs

ISAPI filters must export two functions GetFilterVersion and HttpFilterProc . They can export one additional function, TerminateFilter . GetFilterVersion tells IIS which version number the filter uses and what notifications the filter wants. HttpFilterProc handles the basic operation of the filter. IIS calls the optional function, TerminateFilter, upon termination of the filter, allowing the filter to clean up any resources allocated during processing.

GetFilterVersion

GetFilterVersion , shown in the next code fragment, is the first function an ISAPI filter must implement. This version is called once when the filter is loaded and is not called again.

 BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION  pVer  ); 

The pVer parameter is a pointer to an HTTP_FILTER_VERSION structure. The job of GetFilterVersion is to fill in this structure.

 typedef struct _HTTP_FILTER_VERSION {     DWORD  dwServerFilterVersion;     DWORD  dwFilterVersion;     CHAR   lpszFilterDesc[SF_MAX_FILTER_DESC_LEN];     DWORD  dwFlags; } HTTP_FILTER_VERSION; 

The ISAPI version supported by the Web server is returned in the dwServerFilterVersion member. The second member of the structure, dwFilterVersion , should be set to the ISAPI version of the filter DLL. Some UI elements of IIS use a longer name for the ISAPI filter. This name must be placed in lpszFilterDesc . The final data member, dwFlags, can contain any of the values listed in Table 11-1. The values are broadly grouped into three areas:

  • Requests for notifications
  • Filter priority settings
  • Port security settings

GetFilterVersion must return true for the filter to be activated. If the function returns false , an error event will be logged recording the failure loading the filter. If you do not want the failure to be logged, you must call SetLastError with a value of NO_ERROR. Otherwise, call SetLastError with an appropriate Win32 error code; that code will be used when recording the failure to load.

Table 11-1 ISAPI Filter Flags

Notification Constant Description
SF_NOTIFY_READ_RAW_DATA Indicates the filter should receive notification when data is being read from the client (This can occur more than once per request.)
SF_NOTIFY_PREPROC_HEADERS Indicates the filter should receive notification just after preprocessing headers but before any processing of content
SF_NOTIFY_URL_MAP Indicates the filter should receive notification after the server has converted a URL to a physical path
SF_NOTIFY_AUTHENTICATION Indicates the filter should receive notification just before the server authenticates the client
SF_NOTIFY_ACCESS_DENIED Indicates the filter should receive notification just after the server has determined that the client will be denied access but before notification of the client
SF_NOTIFY_SEND_RESPONSE Indicates the filter should receive notification after the server has processed the request but before any headers are sent to the client
SF_NOTIFY_SEND_RAW_DATA Indicates the filter should receive notification as the server sends raw data back to the client (This can occur more than once per request.)
SF_NOTIFY_END_OF_REQUEST Indicates the filter should receive notification at the end of the request
SF_NOTIFY_LOG Indicates the filter should receive notification at the end of the request, just before the server writes the log for the transaction
SF_NOTIFY_NET_END_OF_SESSION Indicates the filter should receive notification when the network session with the client is ending
SF_NOTIFY_ORDER_DEFAULT Indicates the filter should use the default priority level (low priority)
SF_NOTIFY_ORDER_LOW Indicates the filter should use a low priority level
SF_NOTIFY_ORDER_MEDIUM Indicates the filter should use a medium priority level
SF_NOTIFY_ORDER_HIGH Indicates the filter should use a high priority level
SF_NOTIFY_SECURE_PORT Indicates the filter should receive notifications for requests on a secure port ( https )
SF_NOTIFY_NONSECURE_PORT Indicates the filter should receive notifications for requests on a nonsecure port

HttpFilterProc

HttpFilterProc performs most of the work in an ISAPI filter. This is the function that IIS calls whenever one of the notifications requested by GetFilterVersion occurs.

 DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc,    DWORD notificationType,    LPVOID pvNotification); 

The first parameter, pfc , is a pointer to a filter context structure. This structure is the key to accessing information from the server because, in addition to several data members , it contains five callback functions used to interact with the server and the client.

 typedef struct _HTTP_FILTER_CONTEXT {   DWORD cbSize;   DWORD Revision;   PVOID ServerContext;   DWORD ulReserved;   BOOL fIsSecurePort;   PVOID pFilterContext;   BOOL (WINAPI * GetServerVariable);    BOOL (WINAPI * AddResponseHeaders);    BOOL (WINAPI * WriteClient);    VOID * (WINAPI * AllocMem);    BOOL (WINAPI * ServerSupportFunction);  } HTTP_FILTER_CONTEXT; 

The first member, cbBytes , contains the size of the structure in bytes. The Revision member provides the revision level of this structure. ServerContext and ulReserved are used by the server and should not be touched. Client requests can come from a secure port or a nonsecure port, and fIsSecurePort is a Boolean value that is true if this request is coming over a secure port. Of course, by using GetFilterVersion, you can request either or both types of requests. Therefore, if you have requested notifications for only secure port requests, this value will always be true. If the filter has any information it wants to associate with this request, it can allocate memory and have pFilterContext point to that buffer. The memory allocated is automatically freed during the SF_NOTIFY_END_OF_SESSION notification.

The next five members of HTTP_FILTER_CONTEXT are callback functions supplied by the server to allow the filter to gather information and interact with the client. GetServerVariable points to a function that allows the filter to get all server variables. Recall that the ISPRaw program (Listing 10-7) displays all server variables generated from an Active Server Pages script. The same variables are available to the filter through GetServerVariable , whose prototype is shown below.

 BOOL WINAPI * GetServerVariable(PHTTP_FILTER_CONTEXT pfc,   LPSTR lpszVariableName,   LPVOID lpvBuffer,   LPDWORD lpdwSize) 

As with all the callback functions in pfc , GetServerVariable accepts as its first parameter a pointer to the HTTP_FILTER_CONTEXT sent as the first parameter to HttpFilterProc . The second parameter is a pointer to the variable namefor instance, SERVER_NAME for the name of the server and AUTH_USER for an authenticated user name. The final two parameters are a pointer to a buffer and the size of the buffer, respectively.

AddResponseHeaders points to a function that allows the filter to add headers to the HTTP response:

 BOOL WINAPI * AddResponseHeaders(PHTTP_FILTER_CONTEXT pfc,    LPSTR lpszHeaders,     LPSTR dwReserved); 

Once again, the filter context is passed as the first parameter. The second parameter, lpszHeaders , should point to a string that contains the headers to send. The headers must be in the format "header:value\r\n". The last parameter is reserved.

WriteClient points to a function that allows the filter to write raw data back to the client:

 BOOL WINAPI * WriteClient(PHTTP_FILTER_CONTEXT pfc,   LPVOID buffer,   LPDWORD lpdwBytes,   DWORD dwReserved); 

After the first parameter, which should be set to point to the filter context passed into HttpFilterProc , the second and third parameters point to the buffer to be written and a pointer to a DWORD containing the size in bytes of the buffer. The final parameter is reserved.

AllocMem points to a function that allocates memory. Memory allocated with this function is automatically freed when the session ends.

 VOID * WINAPI * AllocMem(PHTTP_FILTER_CONTEXT pfc,   DWORD cbSize,   DWORD dwReserved); 

This function returns the buffer upon success. The filter context is passed as the first parameter, and the size, in bytes, is passed as the second parameter, cbSize . The final parameter is reserved.

ServerSupportFunction points to a function that allows the filter to perform miscellaneous functions:

 BOOL WINAPI * ServerSupportFunction(PHTTP_FILTER_CONTEXT pfc,   enum SF_REQ_TYPE sfReq,   PVOID pData,   DWORD ul1,   DWORD ul2); 

The first parameter is the pointer to the filter context passed to HttpFilterProc . The code that specifies which function should be called is sfReq . Table 11-2 lists the possible values for this parameter.

Table 11-2 Operation Codes for ServerSupportFunction

ServerSupportFunction Value Description
SF_REQ_ADD_HEADERS_ON_DENIAL Adds headers to a server error response
SF_REQ_GET_CONNID Not supported in IIS 4 and later
SF_REQ_NORMALIZE_URL Decodes hex codes, removes illegal characters , and so on
SF_REQ_SET_NEXT_READ_SIZE Sets the number of bytes read during the next raw read
SF_REQ_DISABLE_NOTIFICATIONS Disables specific notifications for the balance of the request
SF_REQ_GET_PROPERTY Can be used to get SF_PROPERTY_INSTANCE_NUM_ID (This can be used to get information out of the metabasethe store where IIS keeps configuration information.)
SF_REQ_SEND_RESPONSE_HEADER Sends a complete HTTP response header to the client
SF_REQ_SET_PROXY_INFO Indicates if the current request is an HTTP Proxy request

The last three parameters to ServerSupportFunction depend on the operation being performed and should be set to 0 or NULL as appropriate when they are not used for a given operation. The use of these parameters is detailed in the MSDN documentation.

The second parameter to HttpFilterProc is notificationType . This is one of the notification types that can be set in GetFilterVersion , listed earlier in Table 11-1. The final parameter is pvNotification , a pointer to a notification-specific structure. Thus, if the notification is SF_NOTIFY_SEND_RAW_DATA, the structure pointed to is HTTP_FILTER_RAW_DATA. MSDN contains details of the structures for all of the notifications.

TerminateFilter

The optional exported function for ISAPI filters is TerminateFilter .

 BOOL WINAPI TerminateFilter(DWORD dwFlags); 

IIS calls this function to indicate that your filter is going to be unloaded. The single parameter, dwFlags , is reserved. TerminateFilter should be used to release any system resources that the filter has acquired .



Inside Server-Based Applications
Inside Server-Based Applications (DV-MPS General)
ISBN: 1572318171
EAN: 2147483647
Year: 1999
Pages: 91

flylib.com © 2008-2017.
If you may any questions please contact us: flylib@qtcs.net