I can not test it. Give it a try.
Code: Select all
; ********
; *
; * Copyright (c) 1995 Process Software Corporation
; *
; * Copyright (c) 1995-1999 Microsoft Corporation
; *
; *
; * Module Name : HttpExt.h
; *
; * Abstract :
; *
; * This Module contains the Structure definitions And prototypes For the
; * HTTP Server Extension Interface used To build ISAPI Applications
; *
; ******************
CompilerIf #PB_Compiler_IsMainFile
EnableExplicit
CompilerEndIf
; /************************************************************
; * Manifest Constants
; ************************************************************/
#HSE_VERSION_MAJOR = 7 ;// major version of this spec
#HSE_VERSION_MINOR = 5 ;// minor version of this spec
#HSE_LOG_BUFFER_LEN = 80
#HSE_MAX_EXT_DLL_NAME_LEN =256
#HSE_VERSION = #HSE_VERSION_MINOR | ( #HSE_VERSION_MAJOR << 16 )
; //
; // the following are the status codes returned by the Extension DLL
; //
#HSE_STATUS_SUCCESS = 1
#HSE_STATUS_SUCCESS_AND_KEEP_CONN = 2
#HSE_STATUS_PENDING = 3
#HSE_STATUS_ERROR = 4
; //
; // The following are the values To request services With the
; // ServerSupportFunction().
; // Values from 0 To 1000 are reserved For future versions of the Interface
#HSE_REQ_BASE = 0
#HSE_REQ_SEND_URL_REDIRECT_RESP = ( #HSE_REQ_BASE + 1 )
#HSE_REQ_SEND_URL = ( #HSE_REQ_BASE + 2 )
#HSE_REQ_SEND_RESPONSE_HEADER = ( #HSE_REQ_BASE + 3 )
#HSE_REQ_DONE_WITH_SESSION = ( #HSE_REQ_BASE + 4 )
#HSE_REQ_END_RESERVED = 1000
; //
; // These are Microsoft specific extensions
; //
#HSE_REQ_MAP_URL_TO_PATH = (#HSE_REQ_END_RESERVED+1)
#HSE_REQ_GET_SSPI_INFO = (#HSE_REQ_END_RESERVED+2)
#HSE_APPEND_LOG_PARAMETER = (#HSE_REQ_END_RESERVED+3)
#HSE_REQ_IO_COMPLETION = (#HSE_REQ_END_RESERVED+5)
#HSE_REQ_TRANSMIT_FILE = (#HSE_REQ_END_RESERVED+6)
#HSE_REQ_REFRESH_ISAPI_ACL = (#HSE_REQ_END_RESERVED+7)
#HSE_REQ_IS_KEEP_CONN = (#HSE_REQ_END_RESERVED+8)
#HSE_REQ_ASYNC_READ_CLIENT = (#HSE_REQ_END_RESERVED+10)
#HSE_REQ_GET_IMPERSONATION_TOKEN = (#HSE_REQ_END_RESERVED+11)
#HSE_REQ_MAP_URL_TO_PATH_EX = (#HSE_REQ_END_RESERVED+12)
#HSE_REQ_ABORTIVE_CLOSE = (#HSE_REQ_END_RESERVED+14)
#HSE_REQ_GET_CERT_INFO_EX = (#HSE_REQ_END_RESERVED+15)
#HSE_REQ_SEND_RESPONSE_HEADER_EX = (#HSE_REQ_END_RESERVED+16)
#HSE_REQ_CLOSE_CONNECTION = (#HSE_REQ_END_RESERVED+17)
#HSE_REQ_IS_CONNECTED = (#HSE_REQ_END_RESERVED+18)
#HSE_REQ_MAP_UNICODE_URL_TO_PATH = (#HSE_REQ_END_RESERVED+23)
#HSE_REQ_MAP_UNICODE_URL_TO_PATH_EX = (#HSE_REQ_END_RESERVED+24)
#HSE_REQ_EXEC_UNICODE_URL = (#HSE_REQ_END_RESERVED+25)
#HSE_REQ_EXEC_URL = (#HSE_REQ_END_RESERVED+26)
#HSE_REQ_GET_EXEC_URL_STATUS = (#HSE_REQ_END_RESERVED+27)
#HSE_REQ_SEND_CUSTOM_ERROR = (#HSE_REQ_END_RESERVED+28)
#HSE_REQ_IS_IN_PROCESS = (#HSE_REQ_END_RESERVED+30)
#HSE_REQ_REPORT_UNHEALTHY = (#HSE_REQ_END_RESERVED+32)
#HSE_REQ_NORMALIZE_URL = (#HSE_REQ_END_RESERVED+33)
#HSE_REQ_VECTOR_SEND = (#HSE_REQ_END_RESERVED+37)
#HSE_REQ_GET_ANONYMOUS_TOKEN = (#HSE_REQ_END_RESERVED+38)
#HSE_REQ_GET_CACHE_INVALIDATION_CALLBACK= (#HSE_REQ_END_RESERVED+40)
#HSE_REQ_GET_UNICODE_ANONYMOUS_TOKEN = (#HSE_REQ_END_RESERVED+41)
#HSE_REQ_GET_TRACE_INFO = (#HSE_REQ_END_RESERVED+42)
#HSE_REQ_SET_FLUSH_FLAG = (#HSE_REQ_END_RESERVED+43)
#HSE_REQ_GET_TRACE_INFO_EX = (#HSE_REQ_END_RESERVED+44)
#HSE_REQ_RAISE_TRACE_EVENT = (#HSE_REQ_END_RESERVED+45)
#HSE_REQ_GET_CONFIG_OBJECT = (#HSE_REQ_END_RESERVED+46)
#HSE_REQ_GET_WORKER_PROCESS_SETTINGS = (#HSE_REQ_END_RESERVED+47)
#HSE_REQ_GET_PROTOCOL_MANAGER_CUSTOM_INTERFACE_CALLBACK = (#HSE_REQ_END_RESERVED+48)
#HSE_REQ_CANCEL_IO = (#HSE_REQ_END_RESERVED+49)
#HSE_REQ_GET_CHANNEL_BINDING_TOKEN = (#HSE_REQ_END_RESERVED+50)
; //
; // Bit Flags For TerminateExtension
; //
; // HSE_TERM_ADVISORY_UNLOAD - Server wants To unload the extension,
; // extension can Return TRUE If OK, FALSE If the server should Not
; // unload the extension
; //
; // HSE_TERM_MUST_UNLOAD - Server indicating the extension is about To be
; // unloaded, the extension cannot refuse.
; //
#HSE_TERM_ADVISORY_UNLOAD = $00000001
#HSE_TERM_MUST_UNLOAD = $00000002
; //
; // Flags For IO Functions, supported For IO Funcs.
; // TF means ServerSupportFunction( HSE_REQ_TRANSMIT_FILE)
; //
#HSE_IO_SYNC = $00000001 ; // For WriteClient
#HSE_IO_ASYNC = $00000002 ; // For WriteClient/TF/EU
#HSE_IO_DISCONNECT_AFTER_SEND = $00000004 ; // For TF
#HSE_IO_SEND_HEADERS = $00000008 ; // For TF
#HSE_IO_NODELAY = $00001000 ; // turn off nagling
; //
; // These three are only used by VectorSend
; //
#HSE_IO_FINAL_SEND = $00000010
#HSE_IO_CACHE_RESPONSE = $00000020
#HSE_IO_TRY_SKIP_CUSTOM_ERRORS = $00000040
; /************************************************************
; * Type Definitions
; ************************************************************/
; //
; // Structure passed To GetExtensionVersion()
; //
Structure HSE_VERSION_INFO
dwExtensionVersion.l
lpszExtensionDesc.a[#HSE_MAX_EXT_DLL_NAME_LEN]
EndStructure
; //
; // Structure passed To extension Procedure on a new request
; //
Prototype GetServerVariable(hConn, lpszVariableName, lpvBuffer, lpdwSize)
Prototype WriteClient(ConnID, Buffer, lpdwBytes, dwReserved)
Prototype ReadClient(ConnID, lpvBuffer, lpdwSize)
Prototype ServerSupportFunction(hConn, dwHSERequest.l, lpvBuffer, lpdwSize, lpdwDataType)
Structure EXTENSION_CONTROL_BLOCK
cbSize.l; // size of this struct.
dwVersion.l; // version info of this spec
ConnID.i ; // Context number not to be modified!
dwHttpStatusCode.l; // HTTP Status code
lpszLogData.a[#HSE_LOG_BUFFER_LEN];// null terminated log info specific to this Extension DLL
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding.l
CompilerEndIf
lpszMethod.l; // REQUEST_METHOD
lpszQueryString.l; // QUERY_STRING
lpszPathInfo.l ; // PATH_INFO
lpszPathTranslated.l; // PATH_TRANSLATED
cbTotalBytes.l; // Total bytes indicated from client
cbAvailable.l ; // Available number of bytes
lpbData.i ; // pointer to cbAvailable bytes
lpszContentType.l; // Content type of client data
GetServerVariable.GetServerVariable
WriteClient.WriteClient
ReadClient.ReadClient
ServerSupportFunction.ServerSupportFunction
EndStructure
; //
; // Bit field of flags that can be on a virtual directory
; //
#HSE_URL_FLAGS_READ = $00000001 ;// Allow For Read
#HSE_URL_FLAGS_WRITE = $00000002 ;// Allow For Write
#HSE_URL_FLAGS_EXECUTE = $00000004 ;// Allow For Execute
#HSE_URL_FLAGS_SSL = $00000008 ;// Require SSL
#HSE_URL_FLAGS_DONT_CACHE = $00000010 ;// Don't cache (vroot only)
#HSE_URL_FLAGS_NEGO_CERT = $00000020 ;// Allow client SSL certs
#HSE_URL_FLAGS_REQUIRE_CERT = $00000040 ;// Require client SSL certs
#HSE_URL_FLAGS_MAP_CERT = $00000080 ;// Map SSL cert To NT account
#HSE_URL_FLAGS_SSL128 = $00000100 ;// Require 128 bit SSL
#HSE_URL_FLAGS_SCRIPT = $00000200 ;// Allow For Script execution
#HSE_URL_FLAGS_MASK = $000003ff
; //
; // Structure For extended information on a URL mapping
; //
Structure HSE_URL_MAPEX_INFO
lpszPath.a[#MAX_PATH]; // Physical path root mapped to
dwFlags.l ; // Flags associated with this URL path
cchMatchingPath.l ; // Number of matching characters in physical path
cchMatchingURL.l ; // Number of matching characters in URL
dwReserved1.l
dwReserved2.l
EndStructure
Structure HSE_UNICODE_URL_MAPEX_INFO
lpszPath.u[#MAX_PATH]; // Physical path root mapped to
dwFlags.l ; // Flags associated with this URL path
cchMatchingPath.l ; // Number of matching characters in physical path
cchMatchingURL.l ; // Number of matching characters in URL
EndStructure
; //
; // PFN_HSE_IO_COMPLETION - callback function For the Async I/O Completion.
; //
Prototype PFN_HSE_IO_COMPLETION(*pECB.EXTENSION_CONTROL_BLOCK, pContect.i, cbIO.l, dwError.l)
; //
; // HSE_TF_INFO defines the type For HTTP SERVER EXTENSION support For
; // ISAPI applications To send files using TransmitFile.
; // A pointer To this object should be used With ServerSupportFunction()
; // For HSE_REQ_TRANSMIT_FILE.
; //
Structure HSE_TF_INFO
; //
; // callback And context information
; // the callback function will be called when IO is completed.
; // the context specified will be used during such callback.
; //
; // These values (If non-NULL) will override the one set by calling
; // ServerSupportFunction() With HSE_REQ_IO_COMPLETION
; //
pfnHseIO.PFN_HSE_IO_COMPLETION
pContext.i
; // file should have been opened With FILE_FLAG_SEQUENTIAL_SCAN
hFile.i
; //
; // HTTP header And status code
; // These fields are used only If HSE_IO_SEND_HEADERS is present in dwFlags
; //
pszStatusCode.s; // HTTP Status Code eg: "200 OK"
BytesToWrite.l; // special value of "0" means write entire file.
Offset.l ; // offset value within the file to start from
pHead.i; // Head buffer to be sent before file data
HeadLength.l; // header length
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding.l
CompilerEndIf
pTail.i; // Tail buffer to be sent after file data
TailLength.l; // tail length
dwFlags.l; // includes HSE_IO_DISCONNECT_AFTER_SEND, ...
EndStructure
; //
; // HSE_SEND_HEADER_EX_INFO allows an ISAPI application To send headers
; // And specify keep-alive behavior in the same call.
; //
Structure HSE_SEND_HEADER_EX_INFO
; //
; // HTTP status code And header
; //
pszStatus.s; // HTTP status code eg: "200 OK"
pszHeader.s; // HTTP header
cchStatus.l; // number of characters in status code
cchHeader.l; // number of characters in header
fKeepConn.l; // keep client connection alive?
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding.l
CompilerEndIf
EndStructure
;
; //
; // Flags For use With HSE_REQ_EXEC_URL
; //
#HSE_EXEC_URL_NO_HEADERS = $02
#HSE_EXEC_URL_IGNORE_CURRENT_INTERCEPTOR = $04
#HSE_EXEC_URL_IGNORE_VALIDATION_AND_RANGE = $10
#HSE_EXEC_URL_DISABLE_CUSTOM_ERROR = $20
#HSE_EXEC_URL_SSI_CMD = $40
#HSE_EXEC_URL_HTTP_CACHE_ELIGIBLE = $80
; //
; // HSE_EXEC_URL_USER_INFO provides a new user content For use With
; // HSE_REQ_EXEC_URL
; //
Structure HSE_EXEC_URL_USER_INFO
hImpersonationToken.i;
*pszCustomUserName ;
*pszCustomAuthType ;
EndStructure
; //
; // HSE_EXEC_URL_ENTITY_INFO describes the entity body To be provided
; // To the executed request using HSE_REQ_EXEC_URL
; //
Structure HSE_EXEC_URL_ENTITY_INFO
cbAvailable.l
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding.l
CompilerEndIf
lpbData.i
EndStructure
; //
; // HSE_EXEC_URL_STATUS provides the status of the last HSE_REQ_EXEC_URL
; // call
; //
Structure HSE_EXEC_URL_STATUS
uHttpStatusCode.u
uHttpSubStatus.u
dwWin32Error.l
EndStructure
; //
; // HSE_EXEC_URL_INFO provides a description of the request To execute
; // on behalf of the ISAPI.
; //
Structure HSE_EXEC_URL_INFO
*pszUrl; // URL to execute
*pszMethod; // Method
*pszChildHeaders; // Request headers for child
*pUserInfo.HSE_EXEC_URL_USER_INFO; // User for new request
*pEntity.HSE_EXEC_URL_ENTITY_INFO; // Entity body for new request
dwExecUrlFlags.l ; // Flags
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding.l
CompilerEndIf
EndStructure
; //
; // HSE_EXEC_UNICODE_URL_USER_INFO provides a new user content For use With
; // HSE_REQ_EXEC_UNICODE_URL
; //
Structure HSE_EXEC_UNICODE_URL_USER_INFO
hImpersonationToken.i
*pszCustomUserName
*pszCustomAuthType
EndStructure
; //
; // HSE_EXEC_UNICODE_URL_INFO provides a description of the request To execute
; // on behalf of the ISAPI.
; //
Structure HSE_EXEC_UNICODE_URL_INFO
*pszUrl; // URL to execute
*pszMethod; // Method
*pszChildHeaders; // Request headers for child
*pUserInfo.HSE_EXEC_UNICODE_URL_USER_INFO; // User for new request
*pEntity.HSE_EXEC_URL_ENTITY_INFO ; // Entity body for new request
dwExecUrlFlags.l ; // Flags
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding.l
CompilerEndIf
EndStructure
; //
; // HSE_CUSTOM_ERROR_INFO structured used in HSE_REQ_SEND_CUSTOM_ERROR
; //
Structure HSE_CUSTOM_ERROR_INFO
*pszStatus
uHttpSubError.u
__padding.u
fAsync.l
EndStructure
; //
; // structures For the HSE_REQ_VECTOR_SEND ServerSupportFunction
; //
; //
; // Types of vector-elements currently supported
; //
#HSE_VECTOR_ELEMENT_TYPE_MEMORY_BUFFER = 0
#HSE_VECTOR_ELEMENT_TYPE_FILE_HANDLE = 1
; //
; // element of the vector
; //
Structure HSE_VECTOR_ELEMENT
ElementType.l; // Type of element (buffer/file/fragment etc)
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding.l
CompilerEndIf
pvContext.i; // The context representing the element to be sent
cbOffset.q ; // Offset from the start of hFile
cbSize.q ; // Number of bytes to send
EndStructure
;
; //
; // The whole vector To be passed To the ServerSupportFunction
; //
Structure HSE_RESPONSE_VECTOR
dwFlags.l; // combination of HSE_IO_* flags
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding1.l
CompilerEndIf
*pszStatus; // Status line to send like "200 OK"
*pszHeaders; // Headers to send
nElementCount.l; // Number of HSE_VECTOR_ELEMENT's
CompilerIf #PB_Compiler_Processor = #PB_Processor_x64
__padding2.l
CompilerEndIf
*lpElementArray.HSE_VECTOR_ELEMENT ; // Pointer to those elements
EndStructure
Prototype PFN_HSE_CACHE_INVALIDATION_CALLBACK(pszUrl)
; //
; // HSE_TRACE_INFO Structure used To get Debug trace info
; // from core web server
; //
Structure HSE_TRACE_INFO
; //
; // Recommendation from IIS To trace the request
; //
fTraceRequest.l
; //
; // The unique trace context ID For the current request
; //
TraceContextId.b[16];
; //
; // Reserved For future use
; //
dwReserved1.l
dwReserved2.l
EndStructure
;
; //
; // HSE_REQ_GET_TRACE_INFO_EX SSF uses
; // the HTTP_TRACE_CONFIGURATION Structure defined in httptrace.h
; //
;
; //
; // HSE_REQ_RAISE_TRACE_EVENT SSF uses
; // the HTTP_TRACE_EVENT Structure defined in httptrace.h
; //
;
; //
; // SSF_REQ_GET_WORKER_PROCESS_SETTINGS returns IWpfSettings pointer.
; // IWpfSettings is defined in the wpframework.h
; //
;
; //
; // SSF_REQ_GET_CONFIG_OBJECT returns INativeConfigurationSystem pointer.
; // INativeConfigurationSystem is defined in the nativerd.h
; //
;
; //
; // HSE_GET_PROTOCOL_MANAGER_CUSTOM_INTERFACE_CALLBACK returns pointer To
; // PFN_HSE_GET_PROTOCOL_MANAGER_CUSTOM_INTERFACE_CALLBACK function type
; //
Prototype PFN_HSE_GET_PROTOCOL_MANAGER_CUSTOM_INTERFACE_CALLBACK(pszProtocolManagerDll, pszProtocolManagerDllInitFunction, dwCustomInterfaceId.l, ppCustomInterface)
; //
; // Flags For determining application type
; //
#HSE_APP_FLAG_IN_PROCESS = 0
#HSE_APP_FLAG_ISOLATED_OOP = 1
#HSE_APP_FLAG_POOLED_OOP = 2
CompilerIf #PB_Compiler_Thread = 0
CompilerError "ISAPI Extensions must be compiled with threadsafe enabled!"
CompilerEndIf
CompilerIf #PB_Compiler_Unicode
;CompilerError "This include is designed to be used in ASCII mode only"
CompilerEndIf
CompilerIf #PB_Compiler_IsMainFile
; GetExtensionVersion is called when the dll is loaded
;
ProcedureDLL.i GetExtensionVersion(*pver.HSE_VERSION_INFO)
*pver\dwExtensionVersion = #HSE_VERSION ; set the version info
;*pver\lpszExtensionDesc = "ISAPI extension test in PureBasic" ; Its a fixed length string so we can just assign the text
PokeS(@*pver\lpszExtensionDesc[0], "ISAPI extension test in PureBasic", -1, #PB_Ascii)
ProcedureReturn #True ; return success. returning False will cause the dll to be unloaded again
EndProcedure
; This is just a small helper function to wrap the GetServerVariable call
; for easier access
;
Procedure.s ServerVariable(*pECB.EXTENSION_CONTROL_BLOCK, Name$)
Protected *Buffer, Size.i, Value$, *Ascii
Size = 1000
*Buffer = AllocateMemory(Size)
*Ascii = Ascii(Name$)
If *pECB\GetServerVariable(*pECB\ConnID, *Ascii, *Buffer, @Size) = #True
Value$ = PeekS(*Buffer, Size, #PB_Ascii)
EndIf
FreeMemory(*Ascii)
FreeMemory(*Buffer)
ProcedureReturn Value$
EndProcedure
; This is the main function that is called for each client request
; *pECB contains all needed data
;
ProcedureDLL.i HttpExtensionProc(*pECB.EXTENSION_CONTROL_BLOCK)
Protected Html$, BytesRead.i, *Buffer, Size.i, Header.HSE_SEND_HEADER_EX_INFO, Length.i, *Ascii
; Lets build some HTML code to send back
;
Html$ = "<html><head><title>ISAPI extension test in PureBasic</title></head><body>"
Html$ + "<br><hr><center>ISAPI extension test in PureBasic</center><hr>"
Html$ + "<br><br>"
; Some information is directly provided through the structure, other stuff
; can be read with the GetServerVariable callback:
;
Html$ + "Some examples for input data:<hr>"
Html$ + "<b>REQUEST METHOD:</b> " + PeekS(*pECB\lpszMethod, -1, #PB_Ascii) + "<br>"
Html$ + "<b>QUERY_STRING:</b> " + PeekS(*pECB\lpszQueryString, -1, #PB_Ascii) + "<br>"
Html$ + "<b>PATH_INFO:</b> " + PeekS(*pECB\lpszPathInfo, -1, #PB_Ascii) + "<br>"
Html$ + "<b>PATH_TRANSLATED:</b> " + PeekS(*pECB\lpszPathTranslated, -1, #PB_Ascii) + "<br>"
Html$ + "<b>CONTENT TYPE:</b> " + PeekS(*pECB\lpszContentType, -1, #PB_Ascii) + "<br>"
Html$ + "<b>REMOTE_ADDR:</b> " + ServerVariable(*pECB, "REMOTE_ADDR") + "<br>"
Html$ + "<br><br>"
Html$ + "DATA sent from the client:(" + Str(*pECB\cbTotalBytes) + " Bytes)<hr>"
Html$ + "<pre>"
; An important note on POST data from the client:
;
; 'cbTotalBytes' indicates the total number of bytes available from the client.
; 'cbAvailable' indicates the number of bytes directly available in the 'lpbData'
; Buffer. These two may differ (for larger number of datas). So the correct way is
; to read anything inside 'lpbData', and then call the ReadClient() callback as shown
; below until all data is read from the client, if there is more than 'cbAvailable' bytes available
;
If *pECB\cbAvailable > 0
Html$ + PeekS(*pECB\lpbData, *pECB\cbAvailable, #PB_Ascii)
EndIf
If *pECB\cbTotalBytes > *pECB\cbAvailable
BytesRead = *pECB\cbAvailable
*Buffer = AllocateMemory(1000)
If *Buffer
While BytesRead < *pECB\cbTotalBytes
Size = 1000
*pECB\ReadClient(*pECB\ConnID, *Buffer, @Size)
Html$ + PeekS(*Buffer, Size, #PB_Ascii)
BytesRead + Size
Wend
FreeMemory(*Buffer)
EndIf
EndIf
Html$ + "</pre>"
Html$ + "<br><br>"
Html$ + "Test: Enter something and it will be sent to the dll via POST method.<hr>"
Html$ + "<form action="+ #DQUOTE$ +ServerVariable(*pECB, "URL")+ #DQUOTE$ +" method=POST>"
Html$ + "<textarea name="+ #DQUOTE$ +"text"+ #DQUOTE$ +" rows=10 cols=60>Enter text</textarea><br>"
Html$ + "<input type=submit>"
Html$ + "</form>"
Html$ + "</body></html>"
; Send the response header with the ServerSupportFunction() callback
;
Header\pszStatus = "200 OK"
Header\pszHeader = "Content-type: text/html" + #CRLF$ + #CRLF$
Header\cchStatus = StringByteLength(Header\pszStatus, #PB_Ascii)
Header\cchHeader = StringByteLength(Header\pszHeader, #PB_Ascii)
Header\fKeepConn = 0
*pECB\ServerSupportFunction(*pECB\ConnID, #HSE_REQ_SEND_RESPONSE_HEADER_EX, @Header, 0, 0)
; Send the html data with the WriteClient() callback:
;
Length = StringByteLength(Html$, #PB_Ascii)
*Ascii = Ascii(Html$)
*pECB\WriteClient(*pECB\ConnID, *Ascii, @Length, 0)
FreeMemory(*Ascii)
; return success
;
ProcedureReturn #HSE_STATUS_SUCCESS
EndProcedure
; TerminateExtension is called before unloading the dll.
;
ProcedureDLL.i TerminateExtension(dwFlags.l)
ProcedureReturn #True
EndProcedure
CompilerEndIf