ISAPI Filter
Posted: Mon Jun 10, 2019 2:51 am
Has anyone done anything with Microsoft ISAPI filters? I've written a number of extensions that seem to work very well, but I cannot get IIS to call the HttpFilterProc() function. GetFilterVersion() seems to be fine. See below for debug view output.
Here is my barebones program, only enough code to do the minimum needed to run:
All it should do is output strings to DebugView. As Freak has previously documented, you need to run DebugView in Administrator mode, and check Capture Global Win32, to see the output. It SHOULD list a call to GetFilterVersion(), then calls to HttpFilterProc() for each page requested, based upon the notifications requested. All I get is the call to GetFilterVersion():Any help would be appreciated, and I will post my entire program if I can get it running.
Here is my barebones program, only enough code to do the minimum needed to run:
Code: Select all
EnableExplicit
#PROGRAM_NAME = "ots_isapi_filter.dll"
#PROGRAM_VERSION = "1.0.01a." + #PB_Editor_BuildCount
#HSE_VERSION_MAJOR = 7; // major version of this spec
#HSE_VERSION_MINOR = 0; // minor version of this spec
#HTTP_FILTER_REVISION = #HSE_VERSION_MINOR | ( #HSE_VERSION_MAJOR << 16 )
#SF_MAX_USERNAME = 256 + 1
#SF_MAX_PASSWORD = 256 + 1
#SF_MAX_AUTH_TYPE = 32 + 1
#SF_MAX_FILTER_DESC_LEN = 256 + 1
; // These values are returned by the filter entry point when a new request is received indicating their interest in this particular request
#SF_STATUS_REQ_FINISHED = $8000000
#SF_STATUS_REQ_NEXT_NOTIFICATION = #SF_STATUS_REQ_FINISHED + 2
Prototype GetServerVariable(hConnID.i, lpszVariableName.i, lpvBuffer.i, lpdwSize.l)
Prototype AddResponseHeaders(hConnID.i, lpszHeaders.i, dwReserved.l)
Prototype WriteClient(hConnID.i, lpvBuffer.i, lpdwBytes.i, dwReserved.l)
Prototype AllocMem(hConnID.i, cbSize.l, dwReserved.l)
Prototype ServerSupportFunction(hConnID.i, sfReq.i, pData.i, ul1.i, ul2.i)
; // pvNotification points to this structure for all request notification types
Structure HTTP_FILTER_CONTEXT
cbSize.l; // Size of this structure.
Revision.l; // Version info of this spec.
*ServerContext; // Reserved for server use.
ulReserved.l; // Reserved For server use.
fIsSecurePort.l; // A value of TRUE indicates that this event is over a secure port. A value of FALSE indicates that the event is not over a secure port.
*pFilterContext; // Points to any context information that the filter wants to associate with this request.
GetServerVariable.GetServerVariable; // Function call.
AddResponseHeaders.AddResponseHeaders; // Function call.
WriteClient.WriteClient; // Function call.
AllocMem.AllocMem; // Function call.
ServerSupportFunction.ServerSupportFunction; // Function call.
EndStructure
; // This structure is the notification info for when the server is about to process the client headers
Prototype GetHeader(*pfc.HTTP_FILTER_CONTEXT, lpszName.s, lpvBuffer.i, lpdwSize.l)
; // Replaces this header value to the specified value. To delete a header, specified a value of '\0'.
Prototype SetHeader(*pfc.HTTP_FILTER_CONTEXT, lpszName.s, lpszValue.s)
; // Adds the specified header and value
Prototype AddHeader(*pfc.HTTP_FILTER_CONTEXT, lpszName.s, lpszValue.s)
Structure HTTP_FILTER_PREPROC_HEADERS
GetHeader.GetHeader; // Get header function call.
SetHeader.SetHeader; // Set header function call.
AddHeader.AddHeader; // Add header function call.
HttpStatus.l; // Status for SEND_RESPONSE.
dwReserved.l; // Reserved for future use.
EndStructure
#SF_NOTIFY_SECURE_PORT = $00000001
#SF_NOTIFY_NONSECURE_PORT = $00000002
#SF_NOTIFY_SEND_RESPONSE = $00000040
#SF_NOTIFY_PREPROC_HEADERS = $00004000
#SF_NOTIFY_ORDER_HIGH = $00080000
#SF_NOTIFY_ORDER_MEDIUM = $00040000
#SF_NOTIFY_ORDER_LOW = $00020000
#SF_NOTIFY_ORDER_DEFAULT = #SF_NOTIFY_ORDER_LOW
#SF_NOTIFY_ORDER_MASK = #SF_NOTIFY_ORDER_HIGH | #SF_NOTIFY_ORDER_MEDIUM | #SF_NOTIFY_ORDER_LOW
; // Structure passed To GetFilterVersion
Structure HTTP_FILTER_VERSION
dwServerFilterVersion.l; // The ISAPI version in use by the server.
dwFilterVersion.l; // The version number of ISAPI used by the ISAPI filter. The version used by your filter can be set by using the HTTP_FILTER_REVISION definition from the httpfilt.h header file.
lpszFilterDesc.a[#SF_MAX_FILTER_DESC_LEN]; // String for short description of the ISAPI filter. Length = #SF_MAX_FILTER_DESC_LEN
dwFlags.l; // Contains flags that indicate for which notification event types the filter should be notified, and what the filter's priority is. The following table lists the valid bitmasks.
EndStructure
; ************************************************************************************
; initialization procedure
; ************************************************************************************
ProcedureDLL.i AttachProcess(instance.i)
EndProcedure
; ************************************************************************************
; DetachProcess
; ************************************************************************************
ProcedureDLL.i DetachProcess(instance.i)
EndProcedure
; ************************************************************************************
; AttachThread
; ************************************************************************************
ProcedureDLL.i AttachThread(instance.i)
EndProcedure
; ************************************************************************************
; DetachThread
; ************************************************************************************
ProcedureDLL.i DetachThread(instance.i)
EndProcedure
; ************************************************************************************
; GetFilterVersion is called when the dll is loaded
; ************************************************************************************
ProcedureDLL.l GetFilterVersion(*pVer.HTTP_FILTER_VERSION)
Protected logText.s
Protected notifyVersion.l
Protected description.s = "ISAPI Filter written in PureBasic"
Protected descriptionSize.i = StringByteLength(description, #PB_UTF8)
Protected netSource.s = #PROGRAM_NAME + ", version " + #PROGRAM_VERSION + ", GetFilterVersion() > "
Protected notifyFlags.l = #SF_NOTIFY_SEND_RESPONSE | #SF_NOTIFY_ORDER_DEFAULT | #SF_NOTIFY_PREPROC_HEADERS
notifyVersion = #HTTP_FILTER_REVISION
If notifyVersion > *pVer\dwServerFilterVersion
notifyVersion = *pVer\dwServerFilterVersion
EndIf
*pVer\dwFilterVersion = notifyVersion
PokeS(@*pVer\lpszFilterDesc, description, descriptionSize, #PB_UTF8)
*pVer\dwFlags = notifyFlags
logText = netSource + "ISAPI Version: 0x" + RSet(Hex(*pVer\dwServerFilterVersion, #PB_Long), 8, "0")
logText + ", program version: 0x" + RSet(Hex(notifyVersion), 8, "0")
logText + ", notifications requested: 0x" + RSet(Hex(notifyFlags, #PB_Long), 8, "0")
OutputDebugString_(logText)
; return true, returning false will cause the dll to be unloaded
ProcedureReturn #True
EndProcedure
; ************************************************************************************
; This is the main function that is called for each client request pECB contains all needed data
; ************************************************************************************
ProcedureDLL.l HttpFilterProc(*pfc.HTTP_FILTER_CONTEXT, notificationType.l, *pvNotification)
OutputDebugString_(#PROGRAM_NAME + ", version " + #PROGRAM_VERSION + ", HttpFilterProc() called by " + Str(notificationType))
ProcedureReturn #SF_STATUS_REQ_NEXT_NOTIFICATION
EndProcedure
; ************************************************************************************
; TerminateFilter is called before unloading the dll.
; ************************************************************************************
ProcedureDLL.l TerminateFilter(dwFlags)
OutputDebugString_(#PROGRAM_NAME + ", version " + #PROGRAM_VERSION + ", TerminateFilter() called")
ProcedureReturn #True
EndProcedure
; IDE Options = PureBasic 5.70 LTS (Windows - x64)
; ExecutableFormat = Shared dll
; CursorPosition = 115
; FirstLine = 105
; EnableThread
; Executable = ots_iisapi_filter.dll
; DisableDebugger
; HideErrorLog
; DisableCompileCount = 2
; EnableBuildCount = 8
; EnableExeConstant
Code: Select all
[14268] ots_isapi_filter.dll, version 1.0.01a.7, GetFilterVersion() > ISAPI Version: 0x000A0000, program version: 0x00070000, notifications requested: 0x00020043