[MSDN]Creating Simple ISAPI Filters

來自MSDN:  http://msdn.microsoft.com/library/default.asp?url=/library/en-us/iissdk/iis/creating_simple_isapi_filters.asp
For an ISAPI filter to be used by IIS, it must provide a standard interface. To provide a standard interface, each filter application must implement and export two primary functions, GetFilterVersion and HttpFilterProc. A third function, TerminateFilter, is considered optional and is commonly used by filters to perform cleanup operations.

Example Code

The following example shows you how to use the C++ programming language to create a simple ISAPI filter. This filter converts HTML response data to uppercase letters if the client requests it. The request is made by specifying an extra subdirectory in the URL called "UC," which doesn't actually exist on the server, but which is used by the filter to indicate that uppercase letters have been requested. The extra subdirectory is removed from the request before the HTTP server receives the request.

When a request is received, the filter inspects the subdirectories that are specified in the URL. If the nonexistent subdirectory is "UC" or "uc", the subdirectory is removed from the request, and the filter saves a value in its pFilterContext field, that indicates that the response data should be converted to uppercase letters.

When the filter entry point is later called for the response, it checks the pFilterContext field and converts the data if the mime-type of the response indicates that its an HTML file. This avoids conversions on binary data.

This code example is taken from the UpCase sample files that are included with the IIS section of the Platform SDK. It can also be downloaded from Platform SDK Update.

[C++]
/*
  Copyright (c) Microsoft Corporation
  Module Name: upcase.c
*/

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <httpfilt.h>

BOOL WINAPI __stdcall GetFilterVersion(HTTP_FILTER_VERSION *pVer)
{
  /* Specify the types and order of notification */

  pVer->dwFlags = (SF_NOTIFY_NONSECURE_PORT | SF_NOTIFY_URL_MAP |  SF_NOTIFY_SEND_RAW_DATA | SF_NOTIFY_ORDER_DEFAULT);

  pVer->dwFilterVersion = HTTP_FILTER_REVISION;

  strcpy(pVer->lpszFilterDesc, "Upper case conversion filter, Version 1.0");

  return TRUE;
}

DWORD WINAPI __stdcall HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType, VOID *pvData)
{
  CHAR *pchIn, *pPhysPath;
  DWORD  cbBuffer,  cbtemp;
  PHTTP_FILTER_URL_MAP pURLMap;
  PHTTP_FILTER_RAW_DATA  pRawData;

  switch (NotificationType)  {

    case SF_NOTIFY_URL_MAP :

      /* Check the URL for a subdirectory in the form of /UC/ or /uc/ */

      pURLMap  =  (PHTTP_FILTER_URL_MAP)pvData;

      pPhysPath  =  pURLMap->pszPhysicalPath;

      pfc->pFilterContext  =  0;

      for ( ; *pPhysPath; pPhysPath++) 
      {
        /* Ensure that there are at least 4 characters (checking for "/UC/") left in the URL before checking */

        if (strlen(pPhysPath) > 3) 
        {
          if (*pPhysPath == '//' && (*(pPhysPath + 1) == 'u' || *(pPhysPath + 1) == 'U') && (*(pPhysPath + 2) == 'c' || *(pPhysPath + 2) == 'C') && *(pPhysPath + 3) ==  '//')
          {
            /* Now that we've found it, remove it by collapsing everything down */

            for ( ; *(pPhysPath + 3) ; pPhysPath++)
              *pPhysPath = *(pPhysPath + 3);

            /* NULL terminate the string */

            *pPhysPath = '/0'; 

            /* And set the flag to let the SF_NOTIFY_SEND_RAW_DATA handler know to uppercase the content */

            pfc->pFilterContext  =  (VOID  *)1;

            /* Break us out of the loop - note that this will only find the first instance of /UC/ in the URL */

            break;
          }
        }
      }

      break;

    case SF_NOTIFY_SEND_RAW_DATA :

      if (pfc->pFilterContext)
      {
        pRawData = (PHTTP_FILTER_RAW_DATA)pvData;

        pchIn  =  (BYTE  *)pRawData->pvInData;

        cbBuffer = 0;

        if (pfc->pFilterContext  == (VOID *)1)
        {
          /* 
          As this is the first block, scan through it until 2 CRLFs are seen, to pass
          all of the headers.
          */

          for ( ; cbBuffer < pRawData->cbInData - 2; cbBuffer++)
          {
            if (pchIn[cbBuffer]  == '/n' && pchIn[cbBuffer + 2]  == '/n')
            {
              cbBuffer += 3;

              break;
            }

            cbBuffer++;
          }

          for (cbtemp = 0; cbtemp < (cbBuffer - 3); cbtemp++) 
          {
            if (pchIn[cbtemp] == '/' && pchIn[cbtemp + 1] == 'h' && pchIn[cbtemp + 2] == 't' && pchIn[cbtemp + 3] == 'm')
            {
              pfc->pFilterContext  =  (VOID  *)2;

              break;
            }
          }

          if (cbtemp ==  cbBuffer)
            pfc->pFilterContext  =  0; /* not an  html file */
        }

        /* Now uppercase everything */

        if (pfc->pFilterContext)
          for ( ; cbBuffer < pRawData->cbInData; cbBuffer++)
            pchIn[cbBuffer] = (pchIn[cbBuffer] >= 'a' && pchIn[cbBuffer] <= 'z') ? (pchIn[cbBuffer] - 'a' + 'A') : pchIn[cbBuffer];
      }

      break;

    default :

      break;        
  }
  
  return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
發佈了21 篇原創文章 · 獲贊 0 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章