ISAPI Extension conversion for Unicode

Just starting out? Need help? Post your questions and find answers here.
swhite
Enthusiast
Enthusiast
Posts: 726
Joined: Thu May 21, 2009 6:56 pm

ISAPI Extension conversion for Unicode

Post by swhite »

Hi

Freak has kindly created a useful ISAPI 64 bit extension for Windows IIS. However, it requires compilation in ASCII mode. Freak does not currently have the time to update it at the present but did indicate what needs to be done:

Code: Select all

What would need to be done for unicode compatibility is to change all use of fixed length strings in the structures to arrays of ascii characters (.a) and all use of non-fixed strings with pointers. Then all access to these fields would need to be done through PeekS/PokeS with the #PB_Ascii flag to do a conversion.
I wondered if anyone here had the time to convert it so that it worked when compiled in Unicode. I would consider offering some remuneration to get this done as I also am too busy with other projects to work on this at the present time. The updated code would also be made available to the PB community.

Simon
Simon White
dCipher Computing
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: ISAPI Extension conversion for Unicode

Post by infratec »

Hi,

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
Bernd
swhite
Enthusiast
Enthusiast
Posts: 726
Joined: Thu May 21, 2009 6:56 pm

Re: ISAPI Extension conversion for Unicode

Post by swhite »

Hi

I am busy on another project at the moment but I will give it a try soon and let you know what I find. I also want to say thank-you for your assistance.

Simon
Simon White
dCipher Computing
swhite
Enthusiast
Enthusiast
Posts: 726
Joined: Thu May 21, 2009 6:56 pm

Re: ISAPI Extension conversion for Unicode

Post by swhite »

Code: Select all

 *pECB\GetServerVariable(*pECB\ConnID, *Ascii, *Buffer, @Size)
The code above causes a C0000005 error. The values for the parameters are as follows:

*pECB\ConnID = 2636634483400
*Ascii = 2636641930288
*Buffer = 2636641929280
@Size = 509872698680

Simon
Simon White
dCipher Computing
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: ISAPI Extension conversion for Unicode

Post by infratec »

Please try

Code: Select all

 *pECB\GetServerVariable(*pECB\ConnID, @*Ascii, *Buffer, @Size)
swhite
Enthusiast
Enthusiast
Posts: 726
Joined: Thu May 21, 2009 6:56 pm

Re: ISAPI Extension conversion for Unicode

Post by swhite »

Hi

Code: Select all

     *pECB\ReadClient(*pECB\ConnID, *Buffer, @Size)
The above line also produces a C000005 error.

Code: Select all

*pECB\GetServerVariable(*pECB\ConnID, @*Ascii, *Buffer, @Size)
I tested the change suggested above but I still get a C0000005 error.

Simon
Simon White
dCipher Computing
infratec
Always Here
Always Here
Posts: 6817
Joined: Sun Sep 07, 2008 12:45 pm
Location: Germany

Re: ISAPI Extension conversion for Unicode

Post by infratec »

Hi,

explain me how I can test this stuff.

Bernd
swhite
Enthusiast
Enthusiast
Posts: 726
Joined: Thu May 21, 2009 6:56 pm

Re: ISAPI Extension conversion for Unicode

Post by swhite »

Hi

I will send you the details of how to test this in another message, however, I have discovered the source of the problem.

Code: Select all

 If *pECB\cbTotalBytes > *pECB\cbAvailable
The above code in my case is always false because the two values are equal because I am only posting a small amount of json data. So the ASCII compiled version never uses the *pECB\ReadClient(*pECB\ConnID, *rxBuffer, @Size) method. However if I force it to use it then I also get a C0000005 error. The reason the unicode one has an error is because *pECB\cbTotalBytes is huge number in the billions which is obviously not correct. *pECB\cbAvailable is over double the value (493 vs 209) when compiled using ASCII. Thus the unicode version always uses the ReadClient() method.

So there is something wrong with the ReadClient() in both ASCII and Unicode and *pECB\cbTotalBytes and *pECB\cbAvailable are both incorrect in the Unicode mode.

Simon
Simon White
dCipher Computing
JHPJHP
Addict
Addict
Posts: 2129
Joined: Sat Oct 09, 2010 3:47 am
Contact:

Re: ISAPI Extension conversion for Unicode

Post by JHPJHP »

Hi swhite,

See: Services, Stuff & Shellhook
- Stuff\ISAPI\...

The Include file was written from scratch, but the example was based on the following work by freak: http://www.purebasic.fr/english/viewtop ... 12&t=57127

TESTED:
- Windows 10
- PureBasic 5.61 (x86 / x64)

NB*: Various parts of the package can be downloaded separately.
Last edited by JHPJHP on Fri Dec 01, 2017 1:39 am, edited 5 times in total.
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: ISAPI Extension conversion for Unicode

Post by RichAlgeni »

You believe that it is wrong in both ASCII and Unicode mode?
swhite
Enthusiast
Enthusiast
Posts: 726
Joined: Thu May 21, 2009 6:56 pm

Re: ISAPI Extension conversion for Unicode

Post by swhite »

RichAlgeni wrote:You believe that it is wrong in both ASCII and Unicode mode?
I know for sure that is wrong in Unicode mode but I think I should test it more in ASCII mode because after thinking about it some more I might have caused a problem by forcing the ReadClient() even when the the totals bytes equaled the available bytes. So I need to try forcing a situation where the total bytes is more than the available bytes when compiled in ASCII mode.

Simon
Simon White
dCipher Computing
swhite
Enthusiast
Enthusiast
Posts: 726
Joined: Thu May 21, 2009 6:56 pm

Re: ISAPI Extension conversion for Unicode

Post by swhite »

JHPJHP wrote:Hi swhite,

See: Services, Stuff & Shellhook
- Stuff\ISAPI\...

The Include file was written from scratch, but the example was based on the following work by freak: http://www.purebasic.fr/english/viewtop ... 12&t=57127

TESTED:
- Windows 10 (64 bit)
- PureBasic 5.61 (x64)

NB*: Various parts of the package can be downloaded separately.
In my initial quick test this works. I need to do some more testing but thank-you for your help.

Simon
Simon White
dCipher Computing
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: ISAPI Extension conversion for Unicode

Post by RichAlgeni »

I have not used Unicode as of yet, but I do use the Ascii Put functionality all the time, and I've never had an issue with it.
swhite
Enthusiast
Enthusiast
Posts: 726
Joined: Thu May 21, 2009 6:56 pm

Re: ISAPI Extension conversion for Unicode

Post by swhite »

Hi

I was able to do more testing today and my ISAPI extension is working perfectly in Unicode mode now thanks to the ISAPI.pbi file supplied by JHPJHP. I had to change a couple of places to ensure I converted my strings to ASCII but after that everything worked.

Thanks
Simon
Simon White
dCipher Computing
User avatar
RichAlgeni
Addict
Addict
Posts: 914
Joined: Wed Sep 22, 2010 1:50 am
Location: Bradenton, FL

Re: ISAPI Extension conversion for Unicode

Post by RichAlgeni »

:D
Post Reply