2008. augusztus 28., csütörtök

ISAPI Filter Header Files


Problem/Question/Abstract:

In regard to my article "Writing a simple ISAPI Filter for IIS". here you can find the whole translation of the ISAPI Filter Header file HttpFilt.h.

Answer:

Some time ago I wrote an article about ISAPI Filters. Back then I promised to publish the whole translation of the ISAPI Header files. Somehow I never got around to do them, so finally, here they are.

For questions on how to use this definitions refer to my old article, please "Writing a simple ISAPI Filter for IIS".

Some of the definitions may have changed, due to my personal development during the last months, most, however should work as expected. I hope to submit this header translations for the Delphi-Jedi project some time soon.

NOTE: I know that Borland has some of the definitions in the unit Isapi2.pas, however, there are some important changes since version 2. This version depends upon version 4 from Microsoft.

There you go:

{************************************************************************}
{                                                                        }
{       Borland Delphi Runtime Library                                   }
{       HTTP Filter interface unit                                       }
{                                                                        }
{ Portions created by Microsoft are                                      }
{ Copyright (C) 1997 Microsoft Corporation.                              }
{ All Rights Reserved.                                                   }
{                                                                        }
{ The original file is: httpext.h, released 27 January 1999.             }
{ The original Pascal code is: httpext.pas, released 29 April 2002.      }
{ The initial developer of the Pascal code is Daniel Wischnewski         }
{ (daniel@wischnewski.tv).                                               }
{                                                                        }
{ Portions created by Daniel Wischnewski are                             }
{ Copyright (C) 2002 Daniel Wischnewski.                                 }
{                                                                        }
{       Obtained through:                                                }
{                                                                        }
{       Joint Endeavour of Delphi Innovators (Project JEDI)              }
{                                                                        }
{ The contents of this file are used with permission, subject to         }
{ the Mozilla Public License Version 1.1 (the "License"); you may        }
{ not use this file except in compliance with the License. You may       }
{ obtain a copy of the License at                                        }
{ http://www.mozilla.org/MPL/MPL-1.1.html                                }
{                                                                        }
{ Software distributed under the License is distributed on an            }
{ "AS IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or         }
{ implied. See the License for the specific language governing           }
{ rights and limitations under the License.                              }
{                                                                        }
{************************************************************************}

unit HttpFilt;

{$WEAKPACKAGEUNIT}

interface

{$HPPEMIT ''}
{$HPPEMIT '#include "httpfilt.h"'}
{$HPPEMIT '#include "windows.h"'}
{$HPPEMIT ''}

uses
  Windows;

type
  PVOID = Pointer;
{$EXTERNALSYM PVOID}
  LPVOID = Pointer;
{$EXTERNALSYM LPVOID}
  LPSTR = PChar;
{$EXTERNALSYM LPSTR}

  //
  //  Current version of the filter spec is 4.0
  //
const
  HTTP_FILTER_REVISION = WORD(0) + DWORD(4 shl 16);
{$EXTERNALSYM HTTP_FILTER_REVISION}
  SF_MAX_USERNAME = 256 + 1;
{$EXTERNALSYM SF_MAX_USERNAME}
  SF_MAX_PASSWORD = 256 + 1;
{$EXTERNALSYM SF_MAX_PASSWORD}
  SF_MAX_AUTH_TYPE = 32 + 1;
{$EXTERNALSYM SF_MAX_AUTH_TYPE}
  SF_MAX_FILTER_DESC_LEN = 256 + 1;
{$EXTERNALSYM SF_MAX_FILTER_DESC_LEN}

  //
  //  These values can be used with the pfnSFCallback function supplied in
  //  the filter context structure
  //

const
  //
  //  Sends a complete HTTP server response header including
  //  the status, server version, message time and MIME version.
  //
  //  Server extensions should append other information at the end,
  //  such as Content-type, Content-length etc followed by an extra
  //  '\r\n'.
  //
  //  pData - Zero terminated string pointing to optional
  //      status string (i.e., "401 Access Denied") or NULL for
  //      the default response of "200 OK".
  //
  //  ul1 - Zero terminated string pointing to optional data to be
  //      appended and set with the header.  If NULL, the header will
  //      be terminated with an empty line.
  //
  SF_REQ_SEND_RESPONSE_HEADER = 0;
  //
  //  If the server denies the HTTP request, add the specified headers
  //  to the server error response.
  //
  //  This allows an authentication filter to advertise its services
  //  w/o filtering every request.  Generally the headers will be
  //  WWW-Authenticate headers with custom authentication schemes but
  //  no restriction is placed on what headers may be specified.
  //
  //  pData - Zero terminated string pointing to one or more header lines
  //      with terminating '\r\n'.
  //
  SF_REQ_ADD_HEADERS_ON_DENIAL = 1;
  //
  //  Only used by raw data filters that return SF_STATUS_READ_NEXT
  //
  //  ul1 - size in bytes for the next read
  //
  SF_REQ_SET_NEXT_READ_SIZE = 2;
  //
  //  Used to indicate this request is a proxy request
  //
  //  ul1 - The proxy flags to set
  //      0x00000001 - This is a HTTP proxy request
  //
  //
  SF_REQ_SET_PROXY_INFO = 3;
  //
  //  Returns the connection ID contained in the ConnID field of an
  //  ISAPI Application's Extension Control Block.  This value can be used
  //  as a key to cooridinate shared data between Filters and Applications.
  //
  //  pData - Pointer to DWORD that receives the connection ID.
  //
  SF_REQ_GET_CONNID = 4;
  //
  // Used to set a SSPI security context + impersonation token
  // derived from a client certificate.
  //
  // pData - certificate info ( PHTTP_FILTER_CERTIFICATE_INFO )
  // ul1 - CtxtHandle*
  // ul2 - impersonation handle
  //
  SF_REQ_SET_CERTIFICATE_INFO = 5;
  //
  // Used to get an IIS property
  // as defined in SF_PROPERTY_IIS
  //
  // ul1 - Property ID
  //
  SF_REQ_GET_PROPERTY = 6;
  //
  // Used to normalize an URL
  //
  // pData - URL to normalize
  //
  SF_REQ_NORMALIZE_URL = 7;
  //
  // Disable Notifications
  //
  // ul1 - notifications to disable
  //
  SF_REQ_DISABLE_NOTIFICATIONS = 8;
type
  SF_REQ_TYPE = DWORD;
{$EXTERNALSYM SF_REQ_TYPE}
  TSF_REQ_TYPE = SF_REQ_TYPE;

const
  SF_PROPERTY_SSL_CTXT = 0;
  SF_PROPERTY_INSTANCE_NUM_ID = 1;
type
  SF_PROPERTY_IIS = DWORD;
  TSF_PROPERTY_IIS = SF_PROPERTY_IIS;

  //
  //  These values are returned by the filter entry point when a new request is
  //  received indicating their interest in this particular request
  //
const
  //
  //  The filter has handled the HTTP request.  The server should disconnect
  //  the session.
  //
  SF_STATUS_REQ_FINISHED = $8000000;
  //
  //  Same as SF_STATUS_FINISHED except the server should keep the TCP
  //  session open if the option was negotiated
  //
  SF_STATUS_REQ_FINISHED_KEEP_CONN = $8000001;
  //
  //  The next filter in the notification chain should be called
  //
  SF_STATUS_REQ_NEXT_NOTIFICATION = $8000002;
  //
  //  This filter handled the notification.  No other handles should be
  //  called for this particular notification type
  //
  SF_STATUS_REQ_HANDLED_NOTIFICATION = $8000003;
  //
  //  An error occurred.  The server should use GetLastError() and indicate
  //  the error to the client
  //
  SF_STATUS_REQ_ERROR = $8000004;
  //
  //  The filter is an opaque stream filter and we're negotiating the
  //  session parameters.  Only valid for raw read notification.
  //
  SF_STATUS_REQ_READ_NEXT = $8000005;
type
  SF_STATUS_TYPE = DWORD;
  TSF_STATUS_TYPE = SF_STATUS_TYPE;

  //
  //  pvNotification points to this structure for all request notification types
  //
type
  TGetServerVariable = function(var pfc {: THTTP_FILTER_CONTEXT}; lpszVariableName:
    LPSTR; lpvBuffer: LPVOID; var lpdwSize: DWORD): BOOL; stdcall;
  TAddResponseHeaders = function(var pfc {: THTTP_FILTER_CONTEXT}; lpszHeaders: LPSTR;
    dwReserved: DWORD): BOOL; stdcall;
  TWriteClient = function(var pfc {: THTTP_FILTER_CONTEXT}; Buffer: LPVOID; var
    lpdwBytes: DWORD; dwReserved: DWORD): BOOL; stdcall;
  TAllocMem = function(var pfc {: THTTP_FILTER_CONTEXT}; cbSize: DWORD; dwReserved:
    DWORD): Pointer; stdcall;
  TServerSupportFunction = function(var pfc {: THTTP_FILTER_CONTEXT}; sfReq:
    SF_REQ_TYPE; pData: PVOID; ul1: DWORD; ul2: DWORD): BOOL; stdcall;

  PHTTP_FILTER_CONTEXT = ^THTTP_FILTER_CONTEXT;
{$EXTERNALSYM PHTTP_FILTER_CONTEXT}
  _HTTP_FILTER_CONTEXT = packed record
    cbSize: DWORD;
    //
    //  This is the structure revision level.
    //
    Revision: DWORD;
    //
    //  Private context information for the server.
    //
    ServerContext: PVOID;
    ulReserved: DWORD;
    //
    //  TRUE if this request is coming over a secure port
    //
    fIsSecurePort: BOOL;
    //
    //  A context that can be used by the filter
    //
    pFilterContext: PVOID;
    //
    //  Server callbacks
    //
    GetServerVariable: TGetServerVariable;
    AddResponseHeaders: TAddResponseHeaders;
    WriteClient: TWriteClient;
    AllocMem: TAllocMem;
    ServerSupportFunction: TServerSupportFunction;
  end;
{$EXTERNALSYM _HTTP_FILTER_CONTEXT}
  THTTP_FILTER_CONTEXT = _HTTP_FILTER_CONTEXT;

  //
  //  This structure is the notification info for the read and send raw data
  //  notification types
  //
type
  PHTTP_FILTER_RAW_DATA = ^THTTP_FILTER_RAW_DATA;
{$EXTERNALSYM PHTTP_FILTER_RAW_DATA}
  _HTTP_FILTER_RAW_DATA = packed record
    //
    //  This is a pointer to the data for the filter to process.
    //
    pvInData: PVOID;
    cbInData: DWORD; // Number of valid data bytes
    cbInBuffer: DWORD; // Total size of buffer
    dwReserved: DWORD;
  end;
{$EXTERNALSYM _HTTP_FILTER_RAW_DATA}
  THTTP_FILTER_RAW_DATA = _HTTP_FILTER_RAW_DATA;

  //
  //  This structure is the notification info for when the server is about to
  //  process the client headers
  //
type
  TGetHeader = function(var pfc: _HTTP_FILTER_CONTEXT; lpszName: LPSTR; lpvBuffer:
    LPVOID; var lpdwSize: DWORD): BOOL; stdcall;
  TSetHeader = function(var pfc: _HTTP_FILTER_CONTEXT; lpszName: LPSTR; lpszValue:
    LPSTR): BOOL; stdcall;
  TAddHeader = function(var pfc: _HTTP_FILTER_CONTEXT; lpszName: LPSTR; lpszValue:
    LPSTR): BOOL; stdcall;

  PHTTP_FILTER_PREPROC_HEADERS = ^THTTP_FILTER_PREPROC_HEADERS;
{$EXTERNALSYM PHTTP_FILTER_PREPROC_HEADERS}
  _HTTP_FILTER_PREPROC_HEADERS = packed record
    //
    //  For SF_NOTIFY_PREPROC_HEADERS, retrieves the specified header value.
    //  Header names should include the trailing ':'.  The special values
    //  'method', 'url' and 'version' can be used to retrieve the individual
    //  portions of the request line
    //
    GetHeader: TGetHeader;
    //
    //  Replaces this header value to the specified value.  To delete a header,
    //  specified a value of '\0'.
    //
    SetHeader: TSetHeader;
    //
    //  Adds the specified header and value
    //
    AddHeader: TAddHeader;
    HttpStatus: DWORD; // New in 4.0, status for SEND_RESPONSE
    dwReserved: DWORD; // New in 4.0
  end;
{$EXTERNALSYM _HTTP_FILTER_PREPROC_HEADERS}
  THTTP_FILTER_PREPROC_HEADERS = _HTTP_FILTER_PREPROC_HEADERS;

type
  HTTP_FILTER_SEND_RESPONSE = _HTTP_FILTER_PREPROC_HEADERS;
{$EXTERNALSYM HTTP_FILTER_SEND_RESPONSE}
type
  PHTTP_FILTER_SEND_RESPONSE = ^_HTTP_FILTER_PREPROC_HEADERS;
{$EXTERNALSYM PHTTP_FILTER_SEND_RESPONSE}

  //
  //  Authentication information for this request.
  //
type
  PHTTP_FILTER_AUTHENT = ^THTTP_FILTER_AUTHENT;
{$EXTERNALSYM PHTTP_FILTER_AUTHENT}
  _HTTP_FILTER_AUTHENT = packed record
    //
    //  Pointer to username and password, empty strings for the anonymous user
    //
    //  Client's can overwrite these buffers which are guaranteed to be at
    //  least SF_MAX_USERNAME and SF_MAX_PASSWORD bytes large.
    //
    pszUser: PChar;
    cbUserBuff: DWORD;
    pszPassword: PChar;
    cbPasswordBuff: DWORD;
  end;
{$EXTERNALSYM _HTTP_FILTER_AUTHENT}
  THTTP_FILTER_AUTHENT = _HTTP_FILTER_AUTHENT;

  //
  //  Indicates the server is going to use the specific physical mapping for
  //  the specified URL.  Filters can modify the physical path in place.
  //
type
  PHTTP_FILTER_URL_MAP = ^THTTP_FILTER_URL_MAP;
{$EXTERNALSYM PHTTP_FILTER_URL_MAP}
  _HTTP_FILTER_URL_MAP = packed record
    pszURL: PChar;
    pszPhysicalPath: PChar;
    cbPathBuff: DWORD;
  end;
{$EXTERNALSYM _HTTP_FILTER_URL_MAP}
  THTTP_FILTER_URL_MAP = _HTTP_FILTER_URL_MAP;

  //
  //  Bitfield indicating the requested resource has been denied by the server due
  //  to a logon failure, an ACL on a resource, an ISAPI Filter or an
  //  ISAPI Application/CGI Application.
  //
  //  SF_DENIED_BY_CONFIG can appear with SF_DENIED_LOGON if the server
  //  configuration did not allow the user to logon.
  //
const
  SF_DENIED_LOGON = $00000001;
{$EXTERNALSYM SF_DENIED_LOGON}
  SF_DENIED_RESOURCE = $00000002;
{$EXTERNALSYM SF_DENIED_RESOURCE}
  SF_DENIED_FILTER = $00000004;
{$EXTERNALSYM SF_DENIED_FILTER}
  SF_DENIED_APPLICATION = $00000008;
{$EXTERNALSYM SF_DENIED_APPLICATION}

  SF_DENIED_BY_CONFIG = $00010000;
{$EXTERNALSYM SF_DENIED_BY_CONFIG}

type
  PHTTP_FILTER_ACCESS_DENIED = ^THTTP_FILTER_ACCESS_DENIED;
{$EXTERNALSYM PHTTP_FILTER_ACCESS_DENIED}
  _HTTP_FILTER_ACCESS_DENIED = packed record
    pszURL: PChar; // Requesting URL
    pszPhysicalPath: PChar; // Physical path of resource
    dwReason: DWORD; // Bitfield of SF_DENIED flags
  end;
{$EXTERNALSYM _HTTP_FILTER_ACCESS_DENIED}
  THTTP_FILTER_ACCESS_DENIED = _HTTP_FILTER_ACCESS_DENIED;

  //
  //  The log information about to be written to the server log file.  The
  //  string pointers can be replaced but the memory must remain valid until
  //  the next notification
  //
type
  PHTTP_FILTER_LOG = ^THTTP_FILTER_LOG;
{$EXTERNALSYM PHTTP_FILTER_LOG}
  _HTTP_FILTER_LOG = packed record
    pszClientHostName: PChar;
    pszClientUserName: PChar;
    pszServerName: PChar;
    pszOperation: PChar;
    pszTarget: PChar;
    pszParameters: PChar;
    dwHttpStatus: DWORD;
    dwWin32Status: DWORD;
    dwBytesSent: DWORD; // IIS 4.0 and later
    dwBytesRecvd: DWORD; // IIS 4.0 and later
    msTimeForProcessing: DWORD; // IIS 4.0 and later
  end;
{$EXTERNALSYM _HTTP_FILTER_LOG}
  THTTP_FILTER_LOG = _HTTP_FILTER_LOG;

  //
  //  Notification Flags
  //
  //  SF_NOTIFY_SECURE_PORT
  //  SF_NOTIFY_NONSECURE_PORT
  //
  //      Indicates whether the application wants to be notified for transactions
  //      that are happenning on the server port(s) that support data encryption
  //      (such as PCT and SSL), on only the non-secure port(s) or both.
  //
  //  SF_NOTIFY_READ_RAW_DATA
  //
  //      Applications are notified after the server reads a block of memory
  //      from the client but before the server does any processing on the
  //      block.  The data block may contain HTTP headers and entity data.
  //
  //
  //
const
  SF_NOTIFY_SECURE_PORT = $00000001;
{$EXTERNALSYM SF_NOTIFY_SECURE_PORT}
  SF_NOTIFY_NONSECURE_PORT = $00000002;
{$EXTERNALSYM SF_NOTIFY_NONSECURE_PORT}

  SF_NOTIFY_READ_RAW_DATA = $00008000;
{$EXTERNALSYM SF_NOTIFY_READ_RAW_DATA}
  SF_NOTIFY_PREPROC_HEADERS = $00004000;
{$EXTERNALSYM SF_NOTIFY_PREPROC_HEADERS}
  SF_NOTIFY_AUTHENTICATION = $00002000;
{$EXTERNALSYM SF_NOTIFY_AUTHENTICATION}
  SF_NOTIFY_URL_MAP = $00001000;
{$EXTERNALSYM SF_NOTIFY_URL_MAP}
  SF_NOTIFY_ACCESS_DENIED = $00000800;
{$EXTERNALSYM SF_NOTIFY_ACCESS_DENIED}
  SF_NOTIFY_SEND_RESPONSE = $00000040;
{$EXTERNALSYM SF_NOTIFY_SEND_RESPONSE}
  SF_NOTIFY_SEND_RAW_DATA = $00000400;
{$EXTERNALSYM SF_NOTIFY_SEND_RAW_DATA}
  SF_NOTIFY_LOG = $00000200;
{$EXTERNALSYM SF_NOTIFY_LOG}
  SF_NOTIFY_END_OF_REQUEST = $00000080;
{$EXTERNALSYM SF_NOTIFY_END_OF_REQUEST}
  SF_NOTIFY_END_OF_NET_SESSION = $00000100;
{$EXTERNALSYM SF_NOTIFY_END_OF_NET_SESSION}

  //
  //  Filter ordering flags
  //
  //  Filters will tend to be notified by their specified
  //  ordering.  For ties, notification order is determined by load order.
  //
  //  SF_NOTIFY_ORDER_HIGH - Authentication or data transformation filters
  //  SF_NOTIFY_ORDER_MEDIUM
  //  SF_NOTIFY_ORDER_LOW  - Logging filters that want the results of any other
  //                      filters might specify this order.
  //
const
  SF_NOTIFY_ORDER_HIGH = $00080000;
{$EXTERNALSYM SF_NOTIFY_ORDER_HIGH}
  SF_NOTIFY_ORDER_MEDIUM = $00040000;
{$EXTERNALSYM SF_NOTIFY_ORDER_MEDIUM}
  SF_NOTIFY_ORDER_LOW = $00020000;
{$EXTERNALSYM SF_NOTIFY_ORDER_LOW}
  SF_NOTIFY_ORDER_DEFAULT = SF_NOTIFY_ORDER_LOW;
{$EXTERNALSYM SF_NOTIFY_ORDER_DEFAULT}

  SF_NOTIFY_ORDER_MASK = (SF_NOTIFY_ORDER_HIGH or
    SF_NOTIFY_ORDER_MEDIUM or
    SF_NOTIFY_ORDER_LOW);
{$EXTERNALSYM SF_NOTIFY_ORDER_MASK}

  //
  //  Filter version information, passed to GetFilterVersion
  //
type
  PHTTP_FILTER_VERSION = ^THTTP_FILTER_VERSION;
{$EXTERNALSYM PHTTP_FILTER_VERSION}
  _HTTP_FILTER_VERSION = packed record
    //
    //  Version of the spec the server is using
    //
    dwServerFilterVersion: DWORD;
    //
    //  Fields specified by the client
    //
    dwFilterVersion: DWORD;
    lpszFilterDesc: array[0..SF_MAX_FILTER_DESC_LEN - 1] of Char;
    dwFlags: DWORD;
  end;
{$EXTERNALSYM _HTTP_FILTER_VERSION}
  THTTP_FILTER_VERSION = _HTTP_FILTER_VERSION;

  //
  //  A filter DLL's entry point looks like this.  The return code should be
  //  an SF_STATUS_TYPE
  //
  //  NotificationType - Type of notification
  //  pvNotification - Pointer to notification specific data
  //

  //    function GetFilterVersion(var pVer: THTTP_FILTER_VERSION): BOOL; stdcall;
  //    function HttpFilterProc(var pfc: THTTP_FILTER_CONTEXT; NotificationType: DWORD; pvNotification: Pointer): DWORD; stdcall;
  //    function TerminateFilter(dwFlags: DWORD): BOOL; stdcall;

implementation

end.

Nincsenek megjegyzések:

Megjegyzés küldése