You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@tomcat.apache.org by al...@locus.apache.org on 2000/08/26 04:03:56 UTC

cvs commit: jakarta-tomcat/src/native/nt_service jk_nt_service.c nt_service.dsp

alex        00/08/25 19:03:55

  Added:       src/native/mod_jk/iis isapi.def isapi.dsp isapi.dsw
                        jk_isapi_plugin.c
               src/native/mod_jk/jni Makefile.solaris jk_jnicb.c jk_jnicb.h
                        jni_connect.dsp jni_connect.dsw
               src/native/mod_jk/netscape Makefile.solaris
                        jk_nsapi_plugin.c nsapi.dsp nsapi.dsw
               src/native/mod_jk/nt_service jk_nt_service.c nt_service.dsp
  Removed:     src/native/iis isapi.def isapi.dsp isapi.dsw
                        jk_isapi_plugin.c
               src/native/jni_connect Makefile.solaris jk_jnicb.c
                        jk_jnicb.h jni_connect.dsp jni_connect.dsw
               src/native/netscape Makefile.solaris jk_nsapi_plugin.c
                        nsapi.dsp nsapi.dsw
               src/native/nt_service jk_nt_service.c nt_service.dsp
  Log:
  Moved remaining jk directories to mod_jk dir.  Again, I can't test the makefiles, so please test the configuration and let me know if it breaks.  I did my best to change e.g. ..\jk to ..\common but I'm not sure it worked.
  
  Revision  Changes    Path
  1.1                  jakarta-tomcat/src/native/mod_jk/iis/isapi.def
  
  Index: isapi.def
  ===================================================================
  LIBRARY	     "isapi_redirect"
  
  EXPORTS
  	HttpFilterProc
  	GetFilterVersion
  	GetExtensionVersion
  	HttpExtensionProc	
  	TerminateFilter
  	TerminateExtension
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/iis/isapi.dsp
  
  Index: isapi.dsp
  ===================================================================
  # Microsoft Developer Studio Project File - Name="isapi" - Package Owner=<4>
  # Microsoft Developer Studio Generated Build File, Format Version 6.00
  # ** DO NOT EDIT **
  
  # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
  
  CFG=isapi - Win32 Debug
  !MESSAGE This is not a valid makefile. To build this project using NMAKE,
  !MESSAGE use the Export Makefile command and run
  !MESSAGE 
  !MESSAGE NMAKE /f "isapi.mak".
  !MESSAGE 
  !MESSAGE You can specify a configuration when running NMAKE
  !MESSAGE by defining the macro CFG on the command line. For example:
  !MESSAGE 
  !MESSAGE NMAKE /f "isapi.mak" CFG="isapi - Win32 Debug"
  !MESSAGE 
  !MESSAGE Possible choices for configuration are:
  !MESSAGE 
  !MESSAGE "isapi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE "isapi - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE 
  
  # Begin Project
  # PROP AllowPerConfigDependencies 0
  # PROP Scc_ProjName ""
  # PROP Scc_LocalPath ""
  CPP=cl.exe
  MTL=midl.exe
  RSC=rc.exe
  
  !IF  "$(CFG)" == "isapi - Win32 Release"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 0
  # PROP BASE Output_Dir "isapi___Win32_Release"
  # PROP BASE Intermediate_Dir "isapi___Win32_Release"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 0
  # PROP Output_Dir "isapi_release"
  # PROP Intermediate_Dir "isapi_release"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_EXPORTS" /YX /FD /c
  # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\common" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_EXPORTS" /YX /FD /c
  # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x409 /d "NDEBUG"
  # ADD RSC /l 0x409 /d "NDEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
  # ADD LINK32 wsock32.lib advapi32.lib /nologo /dll /machine:I386 /out:"isapi_release/isapi_redirect.dll"
  
  !ELSEIF  "$(CFG)" == "isapi - Win32 Debug"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 1
  # PROP BASE Output_Dir "isapi___Win32_Debug"
  # PROP BASE Intermediate_Dir "isapi___Win32_Debug"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 1
  # PROP Output_Dir "isapi_debug"
  # PROP Intermediate_Dir "isapi_debug"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_EXPORTS" /YX /FD /GZ /c
  # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\common" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "ISAPI_EXPORTS" /YX /FD /GZ /c
  # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x409 /d "_DEBUG"
  # ADD RSC /l 0x409 /d "_DEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
  # ADD LINK32 wsock32.lib advapi32.lib /nologo /dll /debug /machine:I386 /out:"isapi_debug/isapi_redirect.dll" /pdbtype:sept
  
  !ENDIF 
  
  # Begin Target
  
  # Name "isapi - Win32 Release"
  # Name "isapi - Win32 Debug"
  # Begin Group "Source Files"
  
  # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
  # Begin Source File
  
  SOURCE=.\isapi.def
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp12_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_connect.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\jk_isapi_plugin.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_jni_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_lb_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_msg_buff.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_pool.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_sockbuf.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_uri_worker_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_util.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker.c
  # End Source File
  # End Group
  # Begin Group "Header Files"
  
  # PROP Default_Filter "h;hpp;hxx;hm;inl"
  # Begin Source File
  
  SOURCE=..\common\jk_ajp12_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp23_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_connect.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_global.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_jni_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_lb_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_logger.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_msg_buff.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_mt.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_pool.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_service.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_sockbuf.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_uri_worker_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_util.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker_list.h
  # End Source File
  # End Group
  # Begin Group "Resource Files"
  
  # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
  # End Group
  # End Target
  # End Project
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/iis/isapi.dsw
  
  Index: isapi.dsw
  ===================================================================
  Microsoft Developer Studio Workspace File, Format Version 6.00
  # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
  
  ###############################################################################
  
  Project: "isapi"=".\isapi.dsp" - Package Owner=<4>
  
  Package=<5>
  {{{
  }}}
  
  Package=<4>
  {{{
  }}}
  
  ###############################################################################
  
  Global:
  
  Package=<5>
  {{{
  }}}
  
  Package=<3>
  {{{
  }}}
  
  ###############################################################################
  
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/iis/jk_isapi_plugin.c
  
  Index: jk_isapi_plugin.c
  ===================================================================
  /*
   * Copyright (c) 1997-1999 The Java Apache Project.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *
   * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and 
   *    "Java Apache Project" must not be used to endorse or promote products 
   *    derived from this software without prior written permission.
   *
   * 5. Products derived from this software may not be called "Apache JServ"
   *    nor may "Apache" nor "Apache JServ" appear in their names without 
   *    prior written permission of the Java Apache Project.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *    
   * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Java Apache Group. For more information
   * on the Java Apache Project and the Apache JServ Servlet Engine project,
   * please see <http://java.apache.org/>.
   *
   */
  
  /***************************************************************************
   * Description: ISAPI plugin for IIS/PWS                                   *
   * Author:      Gal Shachor <sh...@il.ibm.com>                           *
   * Version:     $Revision: 1.1 $                                               *
   ***************************************************************************/
  
  #include <httpext.h>
  #include <httpfilt.h>
  #include <wininet.h>
  
  #include "jk_global.h"
  #include "jk_util.h"
  #include "jk_map.h"
  #include "jk_pool.h"
  #include "jk_service.h"
  #include "jk_worker.h"
  #include "jk_ajp12_worker.h"
  #include "jk_uri_worker_map.h"
  
  #define VERSION_STRING "Jakarta/ISAPI/1.0b1"
  
  /*
   * We use special two headers to pass values from the filter to the 
   * extension. These values are:
   *
   * 1. The real URI before redirection took place
   * 2. The name of the worker to be used.
   *
   */
  #define URI_HEADER_NAME         ("TOMCATURI:")
  #define WORKER_HEADER_NAME      ("TOMCATWORKER:")
  
  #define HTTP_URI_HEADER_NAME     ("HTTP_TOMCATURI")
  #define HTTP_WORKER_HEADER_NAME  ("HTTP_TOMCATWORKER")
  
  #define REGISTRY_LOCATION       ("Software\\Apache Software Foundation\\Jakarta Isapi Redirector\\1.0")
  #define EXTENSION_URI_TAG       ("extension_uri")
  
  #define GET_SERVER_VARIABLE_VALUE(name, place) {    \
      (place) = NULL;                                   \
      huge_buf_sz = sizeof(huge_buf);                 \
      if(get_server_value(private_data->lpEcb,        \
                          (name),                     \
                          huge_buf,                   \
                          huge_buf_sz,                \
                          "")) {                      \
          (place) = jk_pool_strdup(&private_data->p, huge_buf);   \
      }   \
  }\
  
  #define GET_SERVER_VARIABLE_VALUE_INT(name, place, def) {   \
      huge_buf_sz = sizeof(huge_buf);                 \
      if(get_server_value(private_data->lpEcb,        \
                          (name),                     \
                          huge_buf,                   \
                          huge_buf_sz,                \
                          "")) {                      \
          (place) = atoi(huge_buf);                   \
          if(0 == (place)) {                          \
              (place) = def;                          \
          }                                           \
      } else {    \
          (place) = def;  \
      }           \
  }\
  
  static int   is_inited = JK_FALSE;
  static jk_uri_worker_map_t *uw_map = NULL; 
  static jk_logger_t *logger = NULL; 
  
  static char extension_uri[INTERNET_MAX_URL_LENGTH] = "/jakarta/isapi_redirect.dll";
  static char log_file[MAX_PATH * 2];
  static int  log_level = JK_LOG_EMERG_LEVEL;
  static char worker_file[MAX_PATH * 2];
  static char worker_mount_file[MAX_PATH * 2];
  
  struct isapi_private_data {
      jk_pool_t p;
      
      int request_started;
      unsigned bytes_read_so_far;
      LPEXTENSION_CONTROL_BLOCK  lpEcb;
  };
  typedef struct isapi_private_data isapi_private_data_t;
  
  
  static int JK_METHOD start_response(jk_ws_service_t *s,
                                      int status,
                                      const char *reason,
                                      const char * const *header_names,
                                      const char * const *header_values,
                                      unsigned num_of_headers);
  
  static int JK_METHOD read(jk_ws_service_t *s,
                            void *b,
                            unsigned l,
                            unsigned *a);
  
  static int JK_METHOD write(jk_ws_service_t *s,
                             const void *b,
                             unsigned l);
  
  static int init_ws_service(isapi_private_data_t *private_data,
                             jk_ws_service_t *s,
                             char **worker_name);
  
  static int initialize_extension(void);
  
  static int read_registry_init_data(void);
  
  static int get_registry_config_parameter(HKEY hkey,
                                           const char *tag, 
                                           char *b,
                                           DWORD sz);
  
  
  static int get_server_value(LPEXTENSION_CONTROL_BLOCK lpEcb,
                              char *name,
                              char  *buf,
                              DWORD bufsz,
                              char  *def_val);
  
  static int uri_is_web_inf(char *uri)
  {
      char *c = uri;
      while(*c) {
          *c = tolower(*c);
          c++;
      }                    
      if(strstr(uri, "web-inf")) {
          return JK_TRUE;
      }
  
      return JK_FALSE;
  }
  
  static int JK_METHOD start_response(jk_ws_service_t *s,
                                      int status,
                                      const char *reason,
                                      const char * const *header_names,
                                      const char * const *header_values,
                                      unsigned num_of_headers)
  {
      static char crlf[3] = { (char)13, (char)10, '\0' };
  
      jk_log(logger, JK_LOG_DEBUG, 
             "Into jk_ws_service_t::start_response\n");
  
      if(status < 100 || status > 1000) {
          jk_log(logger, JK_LOG_ERROR, 
                 "jk_ws_service_t::start_response, invalid status %d\n", status);
          return JK_FALSE;
      }
  
      if(s && s->ws_private) {
          isapi_private_data_t *p = s->ws_private;
          if(!p->request_started) {
              DWORD len_of_status;
              char *status_str;
              char *headers_str;
  
              p->request_started = JK_TRUE;
  
              /*
               * Create the status line
               */
              if(!reason) {
                  reason = "";
              }
              status_str = (char *)_alloca((6 + strlen(reason)) * sizeof(char));
              sprintf(status_str, "%d %s", status, reason);
              len_of_status = strlen(status_str); 
          
              /*
               * Create response headers string
               */
              if(num_of_headers) {
                  unsigned i;
                  unsigned len_of_headers;
                  for(i = 0 , len_of_headers = 0 ; i < num_of_headers ; i++) {
                      len_of_headers += strlen(header_names[i]);
                      len_of_headers += strlen(header_values[i]);
                      len_of_headers += 3; /* extra for : and crlf */
                  }
  
                  len_of_headers += 3;  /* crlf and terminating null char */
                  headers_str = (char *)_alloca(len_of_headers * sizeof(char));
                  headers_str[0] = '\0';
  
                  for(i = 0 ; i < num_of_headers ; i++) {
                      strcat(headers_str, header_names[i]);
                      strcat(headers_str, ":");
                      strcat(headers_str, header_values[i]);
                      strcat(headers_str, crlf);
                  }
                  strcat(headers_str, crlf);
              } else {
                  headers_str = crlf;
              }
  
              if(!p->lpEcb->ServerSupportFunction(p->lpEcb->ConnID, 
                                                  HSE_REQ_SEND_RESPONSE_HEADER,
                                                  status_str,
                                                  (LPDWORD)&len_of_status,
                                                  (LPDWORD)headers_str)) {
                  jk_log(logger, JK_LOG_ERROR, 
                         "jk_ws_service_t::start_response, ServerSupportFunction failed\n");
                  return JK_FALSE;
              }       
  
  
          }
          return JK_TRUE;
  
      }
  
      jk_log(logger, JK_LOG_ERROR, 
             "jk_ws_service_t::start_response, NULL parameters\n");
  
      return JK_FALSE;
  }
  
  static int JK_METHOD read(jk_ws_service_t *s,
                            void *b,
                            unsigned l,
                            unsigned *a)
  {
      jk_log(logger, JK_LOG_DEBUG, 
             "Into jk_ws_service_t::read\n");
  
      if(s && s->ws_private && b && a) {
          isapi_private_data_t *p = s->ws_private;
          
          *a = 0;
          if(l) {
              char *buf = b;
              DWORD already_read = p->lpEcb->cbAvailable - p->bytes_read_so_far;
              
              if(already_read >= l) {
                  memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far, l);
                  p->bytes_read_so_far += l;
                  *a = l;
              } else {
                  /*
                   * Try to copy what we already have 
                   */
                  if(already_read > 0) {
                      memcpy(buf, p->lpEcb->lpbData + p->bytes_read_so_far, already_read);
                      buf += already_read;
                      l   -= already_read;
                      p->bytes_read_so_far = p->lpEcb->cbAvailable;
                      
                      *a = already_read;
                  }
                  
                  /*
                   * Now try to read from the client ...
                   */
                  if(p->lpEcb->ReadClient(p->lpEcb->ConnID, buf, &l)) {
                      *a += l;            
                  } else {
                      jk_log(logger, JK_LOG_ERROR, 
                             "jk_ws_service_t::read, ReadClient failed\n");
                      return JK_FALSE;
                  }                   
              }
          }
          return JK_TRUE;
      }
  
      jk_log(logger, JK_LOG_ERROR, 
             "jk_ws_service_t::read, NULL parameters\n");
      return JK_FALSE;
  }
  
  static int JK_METHOD write(jk_ws_service_t *s,
                             const void *b,
                             unsigned l)
  {
      jk_log(logger, JK_LOG_DEBUG, 
             "Into jk_ws_service_t::write\n");
  
      if(s && s->ws_private && b) {
          isapi_private_data_t *p = s->ws_private;
  
          if(l) {
              unsigned written = 0;           
              char *buf = (char *)b;
  
              if(!p->request_started) {
                  start_response(s, 200, NULL, NULL, NULL, 0);
              }
  
              while(written < l) {
                  DWORD try_to_write = l - written;
                  if(!p->lpEcb->WriteClient(p->lpEcb->ConnID, 
                                            buf + written, 
                                            &try_to_write, 
                                            0)) {
                      jk_log(logger, JK_LOG_ERROR, 
                             "jk_ws_service_t::write, WriteClient failed\n");
                      return JK_FALSE;
                  }
                  written += try_to_write;
              }
          }
  
          return JK_TRUE;
  
      }
  
      jk_log(logger, JK_LOG_ERROR, 
             "jk_ws_service_t::write, NULL parameters\n");
  
      return JK_FALSE;
  }
  
  BOOL WINAPI GetFilterVersion(PHTTP_FILTER_VERSION pVer)
  {
      ULONG http_filter_revision = HTTP_FILTER_REVISION 
  
      pVer->dwFilterVersion = pVer->dwServerFilterVersion;
                          
      if(pVer->dwFilterVersion > http_filter_revision) {
          pVer->dwFilterVersion = http_filter_revision;
      }
  
      pVer->dwFlags = SF_NOTIFY_ORDER_HIGH        | 
                      SF_NOTIFY_SECURE_PORT       | 
                      SF_NOTIFY_NONSECURE_PORT    |
                      SF_NOTIFY_PREPROC_HEADERS;
                      
      strcpy(pVer->lpszFilterDesc, VERSION_STRING);
  
      if(!is_inited) {
          return initialize_extension();
      }
  
      return TRUE;
  }
  
  DWORD WINAPI HttpFilterProc(PHTTP_FILTER_CONTEXT pfc,
                              DWORD dwNotificationType, 
                              LPVOID pvNotification)
  {
      if(is_inited &&
         (SF_NOTIFY_PREPROC_HEADERS == dwNotificationType)) { 
          PHTTP_FILTER_PREPROC_HEADERS p = (PHTTP_FILTER_PREPROC_HEADERS)pvNotification;
          char uri[INTERNET_MAX_URL_LENGTH]; 
          char *query;
          DWORD sz = sizeof(uri);
  
          jk_log(logger, JK_LOG_DEBUG, 
                 "HttpFilterProc started\n");
  
          /*
           * Just in case somebody set these headers in the request!
           */
          p->SetHeader(pfc, URI_HEADER_NAME, NULL);
  	    p->SetHeader(pfc, WORKER_HEADER_NAME, NULL);
          
          if(!p->GetHeader(pfc, "url", (LPVOID)uri, (LPDWORD)&sz)) {
              jk_log(logger, JK_LOG_ERROR, 
                     "HttpFilterProc error while getting the url\n");
              return SF_STATUS_REQ_ERROR;
          }
  
          if(strlen(uri)) {
              char *worker;
              query = strchr(uri, '?');
              if(query) {
                  *query = '\0';
              }
              jk_log(logger, JK_LOG_DEBUG, 
                     "In HttpFilterProc test redirection of %s\n", 
                     uri);
              worker = map_uri_to_worker(uw_map, uri, logger);                
              if(query) {
                  *query = '?';
              }
  
              if(worker) {
                  /* This is a servlet, should redirect ... */
                  jk_log(logger, JK_LOG_DEBUG, 
                         "HttpFilterProc [%s] is a servlet url - should redirect to %s\n", 
                         uri, worker);
  
                  
  				if(!p->AddHeader(pfc, URI_HEADER_NAME, uri) || 
                     !p->AddHeader(pfc, WORKER_HEADER_NAME, worker) ||
                     !p->SetHeader(pfc, "url", extension_uri)) {
                      jk_log(logger, JK_LOG_ERROR, 
                             "HttpFilterProc error while adding request headers\n");
                      return SF_STATUS_REQ_ERROR;
                  }
              } else {
                  jk_log(logger, JK_LOG_DEBUG, 
                         "HttpFilterProc [%s] is not a servlet url\n", 
                         uri);
              }
  
              /*
               * Check if somebody is feading us with his own TOMCAT data headers.
               * We reject such postings !
               */
              jk_log(logger, JK_LOG_DEBUG, 
                     "HttpFilterProc check if [%s] is points to the web-inf directory\n", 
                     uri);
  
              if(uri_is_web_inf(uri)) {
                  char crlf[3] = { (char)13, (char)10, '\0' };
                  char ctype[30];
                  char *msg = "<HTML><BODY><H1>Access is Forbidden</H1></BODY></HTML>";
                  DWORD len = strlen(msg);
  
                  jk_log(logger, JK_LOG_EMERG, 
                         "HttpFilterProc [%s] points to the web-inf directory.\nSomebody try to hack into the site!!!\n", 
                         uri);
  
                  sprintf(ctype, 
                          "Content-Type:text/html%s%s", 
                          crlf, 
                          crlf);
  
                  /* reject !!! */
                  pfc->ServerSupportFunction(pfc, 
                                             SF_REQ_SEND_RESPONSE_HEADER,
                                             "403 Forbidden",
                                             (DWORD)crlf,
                                             (DWORD)ctype);
                  pfc->WriteClient(pfc, msg, &len, 0);
  
                  return SF_STATUS_REQ_FINISHED;
              }
          }
      }
      return SF_STATUS_REQ_NEXT_NOTIFICATION;
  }
  
  
  BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO  *pVer)
  {
      pVer->dwExtensionVersion = MAKELONG( HSE_VERSION_MINOR,
                                           HSE_VERSION_MAJOR );
  
      strcpy(pVer->lpszExtensionDesc, VERSION_STRING);
  
  
      if(!is_inited) {
          return initialize_extension();
      }
  
      return TRUE;
  }
  
  DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK  lpEcb)
  {   
      DWORD rc = HSE_STATUS_ERROR;
  
      lpEcb->dwHttpStatusCode = HTTP_STATUS_SERVER_ERROR;
  
      jk_log(logger, JK_LOG_DEBUG, 
             "HttpExtensionProc started\n");
  
      if(is_inited) {
          isapi_private_data_t private_data;
          jk_ws_service_t s;
          jk_pool_atom_t buf[SMALL_POOL_SIZE];
          char *worker_name;
  
          jk_init_ws_service(&s);
          jk_open_pool(&private_data.p, buf, sizeof(buf));
  
          private_data.request_started = JK_FALSE;
          private_data.bytes_read_so_far = 0;
          private_data.lpEcb = lpEcb;
  
          s.ws_private = &private_data;
          s.pool = &private_data.p;
  
          if(init_ws_service(&private_data, &s, &worker_name)) {
              jk_worker_t *worker = wc_get_worker_for_name(worker_name, logger);
  
              jk_log(logger, JK_LOG_DEBUG, 
                     "HttpExtensionProc %s a worker for name %s\n", 
                     worker ? "got" : "could not get",
                     worker_name);
  
              if(worker) {
                  jk_endpoint_t *e = NULL;
                  if(worker->get_endpoint(worker, &e, logger)) {
                      int recover = JK_FALSE;
                      if(e->service(e, &s, logger, &recover)) {
                          rc = HSE_STATUS_SUCCESS_AND_KEEP_CONN;
                          lpEcb->dwHttpStatusCode = HTTP_STATUS_OK;
                          jk_log(logger, JK_LOG_DEBUG, 
                                 "HttpExtensionProc service() returned OK\n");
                      } else {
                          jk_log(logger, JK_LOG_ERROR, 
                                 "HttpExtensionProc error, service() failed\n");
                      }
                      e->done(&e, logger);
                  }
              } else {
                  jk_log(logger, JK_LOG_ERROR, 
                         "HttpExtensionProc error, could not get a worker for name %s\n",
                         worker_name);
              }
          }
          jk_close_pool(&private_data.p);     
      } else {
          jk_log(logger, JK_LOG_ERROR, 
                 "HttpExtensionProc error, not initialized\n");
      }
  
      return rc;
  }
  
      
  
  BOOL WINAPI TerminateExtension(DWORD dwFlags) 
  {
      return TerminateFilter(dwFlags);
  }
  
  BOOL WINAPI TerminateFilter(DWORD dwFlags) 
  {
      if(is_inited) {
          is_inited = JK_FALSE;
  
          uri_worker_map_free(&uw_map, logger);
          wc_close(logger);
          if(logger) {
              jk_close_file_logger(&logger);
          }
      }
      
      return TRUE;
  }
  
  
  BOOL WINAPI DllMain(HINSTANCE hInst,        // Instance Handle of the DLL
                      ULONG ulReason,         // Reason why NT called this DLL
                      LPVOID lpReserved)      // Reserved parameter for future use
  {
      BOOL fReturn = TRUE;
  
      switch (ulReason) {
          case DLL_PROCESS_DETACH:
              __try {
                  TerminateFilter(HSE_TERM_MUST_UNLOAD);
              } __except(1) {
              }
          break;
  
          default:
          break;
      } 
  
      return fReturn;
  }
  
  static int initialize_extension(void)
  {
      int rc = JK_FALSE;  
  
      if(read_registry_init_data()) {
          jk_map_t *map;
  
          if(!jk_open_file_logger(&logger, log_file, log_level)) {
              logger = NULL;
          }
          
          if(map_alloc(&map)) {
              if(map_read_properties(map, worker_mount_file)) {
                  if(uri_worker_map_alloc(&uw_map, map, logger)) {
                      rc = JK_TRUE;
                  }
              }
              map_free(&map);
          }
  
          if(rc) {
              rc = JK_FALSE;
              if(map_alloc(&map)) {
                  if(map_read_properties(map, worker_file)) {
                      if(wc_open(map, logger)) {
                          rc = JK_TRUE;
                      }
                  }
                  map_free(&map);
              }
          }
  
      }
  
      if(rc) {
          is_inited = JK_TRUE;
      }
      return rc;
  }
  
  static int read_registry_init_data(void)
  {
      char tmpbuf[INTERNET_MAX_URL_LENGTH];
      HKEY hkey;
      long rc;
      int  ok = JK_TRUE;
      rc = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                        REGISTRY_LOCATION,
                        (DWORD)0,         
                        KEY_READ,         
                        &hkey);            
      if(ERROR_SUCCESS != rc) {
          return JK_FALSE;
      } 
  
      if(get_registry_config_parameter(hkey,
                                       JK_LOG_FILE_TAG, 
                                       tmpbuf,
                                       sizeof(log_file))) {
          strcpy(log_file, tmpbuf);
      } else {
          ok = JK_FALSE;
      }
      
      if(get_registry_config_parameter(hkey,
                                       JK_LOG_LEVEL_TAG, 
                                       tmpbuf,
                                       sizeof(tmpbuf))) {
          log_level = jk_parse_log_level(tmpbuf);
      } else {
          ok = JK_FALSE;
      }
  
      if(get_registry_config_parameter(hkey,
                                       EXTENSION_URI_TAG, 
                                       tmpbuf,
                                       sizeof(extension_uri))) {
          strcpy(extension_uri, tmpbuf);
      } else {
          ok = JK_FALSE;
      }
  
      if(get_registry_config_parameter(hkey,
                                       JK_WORKER_FILE_TAG, 
                                       tmpbuf,
                                       sizeof(worker_file))) {
          strcpy(worker_file, tmpbuf);
      } else {
          ok = JK_FALSE;
      }
  
      if(get_registry_config_parameter(hkey,
                                       JK_MOUNT_FILE_TAG, 
                                       tmpbuf,
                                       sizeof(worker_mount_file))) {
          strcpy(worker_mount_file, tmpbuf);
      } else {
          ok = JK_FALSE;
      }
  
      RegCloseKey(hkey);
  
      return ok;
  }
  
  static int get_registry_config_parameter(HKEY hkey,
                                           const char *tag, 
                                           char *b,
                                           DWORD sz)
  {   
      DWORD type = 0;
      LONG  lrc;
  
      lrc = RegQueryValueEx(hkey,     
                            tag,      
                            (LPDWORD)0,
                            &type,    
                            (LPBYTE)b,
                            &sz); 
      if((ERROR_SUCCESS != lrc) || (type != REG_SZ)) {
          return JK_FALSE;        
      }
      
      b[sz] = '\0';
  
      return JK_TRUE;     
  }
  
  static int init_ws_service(isapi_private_data_t *private_data,
                             jk_ws_service_t *s,
                             char **worker_name) 
  {
      char huge_buf[16 * 1024]; /* should be enough for all */
  
      DWORD huge_buf_sz;
  
      s->jvm_route = NULL;
  
      s->start_response = start_response;
      s->read = read;
      s->write = write;
  
      GET_SERVER_VARIABLE_VALUE(HTTP_WORKER_HEADER_NAME, (*worker_name));           
      GET_SERVER_VARIABLE_VALUE(HTTP_URI_HEADER_NAME, s->req_uri);     
  
      if(s->req_uri) {
          char *t = strchr(s->req_uri, '?');
          if(t) {
              *t = '\0';
              t++;
              if(!strlen(t)) {
                  t = NULL;
              }
          }
          s->query_string = t;
      } else {
          s->query_string = private_data->lpEcb->lpszQueryString;
          *worker_name    = JK_AJP12_WORKER_NAME;
          GET_SERVER_VARIABLE_VALUE("URL", s->req_uri);       
      }
      
      GET_SERVER_VARIABLE_VALUE("AUTH_TYPE", s->auth_type);
      GET_SERVER_VARIABLE_VALUE("REMOTE_USER", s->remote_user);
      GET_SERVER_VARIABLE_VALUE("SERVER_PROTOCOL", s->protocol);
      GET_SERVER_VARIABLE_VALUE("REMOTE_HOST", s->remote_host);
      GET_SERVER_VARIABLE_VALUE("REMOTE_ADDR", s->remote_addr);
      GET_SERVER_VARIABLE_VALUE("SERVER_NAME", s->server_name);
      GET_SERVER_VARIABLE_VALUE_INT("SERVER_PORT", s->server_port, 80)
      GET_SERVER_VARIABLE_VALUE("SERVER_SOFTWARE", s->server_software);
      GET_SERVER_VARIABLE_VALUE_INT("SERVER_PORT_SECURE", s->is_ssl, 0);
  
      s->method           = private_data->lpEcb->lpszMethod;
      s->content_length   = private_data->lpEcb->cbTotalBytes;
  
      s->ssl_cert     = NULL;
      s->ssl_cert_len = 0;
      s->ssl_cipher   = NULL;
      s->ssl_session  = NULL;
  
      s->headers_names    = NULL;
      s->headers_values   = NULL;
      s->num_headers      = 0;
      
      /*
       * Add SSL IIS environment
       */
      if(s->is_ssl) {         
          char *ssl_env_names[9] = {
              "CERT_ISSUER", 
              "CERT_SUBJECT", 
              "CERT_COOKIE", 
              "HTTPS_SERVER_SUBJECT", 
              "CERT_FLAGS", 
              "HTTPS_SECRETKEYSIZE", 
              "CERT_SERIALNUMBER", 
              "HTTPS_SERVER_ISSUER", 
              "HTTPS_KEYSIZE"
          };
          char *ssl_env_values[9] = {
              NULL, 
              NULL, 
              NULL, 
              NULL, 
              NULL, 
              NULL, 
              NULL, 
              NULL, 
              NULL
          };
          unsigned i;
          unsigned num_of_vars = 0;
  
          for(i = 0 ; i < 9 ; i++) {
              GET_SERVER_VARIABLE_VALUE(ssl_env_names[i], ssl_env_values[i]);
              if(ssl_env_values[i]) {
                  num_of_vars++;
              }
          }
          if(num_of_vars) {
              unsigned j;
  
              s->attributes_names = 
                  jk_pool_alloc(&private_data->p, num_of_vars * sizeof(char *));
              s->attributes_values = 
                  jk_pool_alloc(&private_data->p, num_of_vars * sizeof(char *));
  
              j = 0;
              for(i = 0 ; i < 9 ; i++) {                
                  if(ssl_env_values[i]) {
                      s->attributes_names[j] = ssl_env_names[i];
                      s->attributes_values[j] = ssl_env_values[i];
                      j++;
                  }
              }
              s->num_attributes = num_of_vars;
          }
      }
  
      huge_buf_sz = sizeof(huge_buf);         
      if(get_server_value(private_data->lpEcb,
                          "ALL_HTTP",             
                          huge_buf,           
                          huge_buf_sz,        
                          "")) {              
          unsigned cnt = 0;
          char *tmp;
  
          for(tmp = huge_buf ; *tmp ; tmp++) {
              if(*tmp == '\n'){
                  cnt++;
              }
          }
  
          if(cnt) {
              char *headers_buf = jk_pool_strdup(&private_data->p, huge_buf);
              unsigned i;
              unsigned len_of_http_prefix = strlen("HTTP_");
              
              cnt -= 2; /* For our two special headers */
              s->headers_names  = jk_pool_alloc(&private_data->p, cnt * sizeof(char *));
              s->headers_values = jk_pool_alloc(&private_data->p, cnt * sizeof(char *));
  
              if(!s->headers_names || !s->headers_values || !headers_buf) {
                  return JK_FALSE;
              }
  
              for(i = 0, tmp = headers_buf ; *tmp && i < cnt ; ) {
                  int real_header = JK_TRUE;
  
                  /* Skipp the HTTP_ prefix to the beginning of th header name */
                  tmp += len_of_http_prefix;
  
                  if(!strnicmp(tmp, URI_HEADER_NAME, strlen(URI_HEADER_NAME)) ||
                     !strnicmp(tmp, WORKER_HEADER_NAME, strlen(WORKER_HEADER_NAME))) {
                      real_header = JK_FALSE;
                  } else {
                      s->headers_names[i]  = tmp;
                  }
  
                  while(':' != *tmp && *tmp) {
                      if('_' == *tmp) {
                          *tmp = '-';
                      } else {
                          *tmp = tolower(*tmp);
                      }
                      tmp++;
                  }
                  *tmp = '\0';
                  tmp++;
  
                  /* Skipp all the WS chars after the ':' to the beginning of th header value */
                  while(' ' == *tmp || '\t' == *tmp || '\v' == *tmp) {
                      tmp++;
                  }
  
                  if(real_header) {
                      s->headers_values[i]  = tmp;
                  }
                  
                  while(*tmp != '\n' && *tmp != '\r') {
                      tmp++;
                  }
                  *tmp = '\0';
                  tmp++;
  
                  /* skipp CR LF */
                  while(*tmp == '\n' || *tmp == '\r') {
                      tmp++;
                  }
  
                  if(real_header) {
                      i++;
                  }
              }
              s->num_headers = cnt;
          } else {
              /* We must have our two headers */
              return JK_FALSE;
          }
      } else {
          return JK_FALSE;
      }
      
      return JK_TRUE;
  }
  
  static int get_server_value(LPEXTENSION_CONTROL_BLOCK lpEcb,
                              char *name,
                              char  *buf,
                              DWORD bufsz,
                              char  *def_val)
  {
      if(!lpEcb->GetServerVariable(lpEcb->ConnID, 
                                   name,
                                   buf,
                                   (LPDWORD)&bufsz)) {
          strcpy(buf, def_val);
          return JK_FALSE;
      }
  
      if(bufsz > 0) {
          buf[bufsz - 1] = '\0';
      }
  
      return JK_TRUE;
  }
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/jni/Makefile.solaris
  
  Index: Makefile.solaris
  ===================================================================
  # Defines for example NSAPI programs running under SOLARIS
  
  CC_CMD=gcc -DSOLARIS -D_REENTRANT
  LD_SHAREDCMD=ld -G
  
  all:
  prepare:
  
  OS_TYPE=solaris
  INCLUDEDIR=../common
  JAVA_INCLUDE=$(JAVA_HOME)/include
  
  JK_OBJS =  ../common/jk_map.o ../common/jk_util.o ../common/jk_pool.o jk_jnicb.o
  
  INCLUDE_FLAGS=-I$(INCLUDEDIR) -I$(JAVA_INCLUDE) -I$(JAVA_INCLUDE)/$(OS_TYPE)
  COMMON_DEFS=-Wall
  
  
  all: jni_connect.so 
  
  
  jni_connect.so: $(JK_OBJS)
  	$(MAKE) prepare
  	$(LD_SHAREDCMD) $(JK_OBJS) -o jni_connect.so $(EXTRA_LDDEFINES)
  
  .c.o:
  	$(CC_CMD) $(COMMON_DEFS) $(INCLUDE_FLAGS) -c $< 
  
  clean:
  	rm $(JK_OBJS)
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/jni/jk_jnicb.c
  
  Index: jk_jnicb.c
  ===================================================================
  /*
   * Copyright (c) 1997-1999 The Java Apache Project.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *
   * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and 
   *    "Java Apache Project" must not be used to endorse or promote products 
   *    derived from this software without prior written permission.
   *
   * 5. Products derived from this software may not be called "Apache JServ"
   *    nor may "Apache" nor "Apache JServ" appear in their names without 
   *    prior written permission of the Java Apache Project.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *    
   * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Java Apache Group. For more information
   * on the Java Apache Project and the Apache JServ Servlet Engine project,
   * please see <http://java.apache.org/>.
   *
   */
  
  /***************************************************************************
   * Description: JNI callbacks implementation for the JNI in process adapter*
   * Author:      Gal Shachor <sh...@il.ibm.com>                           *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  #include "jk_jnicb.h"
  #include "jk_service.h"
  #include "jk_util.h"
  #include "jk_pool.h"
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    getNumberOfHeaders
   * Signature: (JJ)I
   */
  JNIEXPORT jint JNICALL 
  Java_org_apache_tomcat_service_connector_JNIConnectionHandler_getNumberOfHeaders
    (JNIEnv *env, jobject o, jlong s, jlong l)
  {
      /* [V] Convert indirectly from jlong -> int -> pointer to shut up gcc */
      /*     I hope it's okay on other compilers and/or machines...         */
      jk_ws_service_t *ps = (jk_ws_service_t *)(int)s;
      jk_logger_t *pl = (jk_logger_t *)(int)l;
  
      jk_log(pl, JK_LOG_DEBUG, "Into JNIConnectionHandler::getNumberOfHeaders\n");
  
      if(!ps) {
  	jk_log(pl, JK_LOG_ERROR, 
                 "In JNIConnectionHandler::getNumberOfHeaders, NULL ws service object\n");
  	/* [V] JNIConnectionHandler doesn't handle this */
  	return -1;
      }
  
      jk_log(pl, JK_LOG_DEBUG,
  	   "Done JNIConnectionHandler::getNumberOfHeaders, found %d headers\n",
  	   ps->num_headers);
      return (jint)ps->num_headers;
  }
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    read
   * Signature: (JJ[BII)I
   */
  JNIEXPORT jint JNICALL 
  Java_org_apache_tomcat_service_connector_JNIConnectionHandler_read
    (JNIEnv *env, jobject o, jlong s, jlong l, jbyteArray buf, jint from, jint cnt)
  {
      jk_ws_service_t *ps = (jk_ws_service_t *)(int)s;
      jk_logger_t *pl = (jk_logger_t *)(int)l;
      jint rc = -1;
      jboolean iscommit;
      jbyte *nbuf;
      unsigned nfrom = (unsigned)from;
      unsigned ncnt = (unsigned)cnt;
      unsigned acc = 0;
  
      jk_log(pl, JK_LOG_DEBUG, "Into JNIConnectionHandler::read\n");
  
      if(!ps) {
          jk_log(pl, JK_LOG_ERROR, 
                 "In JNIConnectionHandler::read, NULL ws service object\n");
  	return -1;
      }
  
      nbuf = (*env)->GetByteArrayElements(env, buf, &iscommit);
  
      if(!nbuf) {
          jk_log(pl, JK_LOG_ERROR, 
                 "In JNIConnectionHandler::read, GetByteArrayElements error\n");
  	return -1;
      }
      
      if(!ps->read(ps, nbuf + nfrom, ncnt, &acc)) {
          jk_log(pl, JK_LOG_ERROR, 
                 "In JNIConnectionHandler::read, failed to read from web server\n");
      } else {
          rc = (jint)acc;
      }
  
      (*env)->ReleaseByteArrayElements(env, buf, nbuf, 0);
  
      jk_log(pl, JK_LOG_DEBUG, "Done JNIConnectionHandler::read\n");
      return rc;
  }
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    readEnvironment
   * Signature: (JJ[Ljava/lang/String;)I
   */
  JNIEXPORT jint JNICALL 
  Java_org_apache_tomcat_service_connector_JNIConnectionHandler_readEnvironment
    (JNIEnv *env, jobject o, jlong s, jlong l, jobjectArray envbuf)
  {
      jk_ws_service_t *ps = (jk_ws_service_t *)(int)s;
      jk_logger_t *pl = (jk_logger_t *)(int)l;
      char port[10];
  
      jk_log(pl, JK_LOG_DEBUG, 
             "Into JNIConnectionHandler::readEnvironment. Environment follows --->\n");
  
      if(!ps) {
          jk_log(pl, JK_LOG_ERROR, 
                 "In JNIConnectionHandler::readEnvironment, NULL ws service object\n");
  	return JK_FALSE;
      }
  
      sprintf(port, "%d", ps->server_port);
          
      if(ps->method) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        0, 
                                        (*env)->NewStringUTF(env, ps->method));
  	jk_log(pl, JK_LOG_DEBUG, "---> method: %s\n", ps->method);
      }
      if(ps->req_uri) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        1, 
                                        (*env)->NewStringUTF(env, ps->req_uri));
  	jk_log(pl, JK_LOG_DEBUG, "---> req_uri: %s\n", ps->req_uri);
      }
      if(ps->query_string) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        2, 
                                        (*env)->NewStringUTF(env, ps->query_string));
          jk_log(pl, JK_LOG_DEBUG, "---> query_string: %s\n", ps->query_string);
      }
      if(ps->remote_addr) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        3, 
                                        (*env)->NewStringUTF(env, ps->remote_addr));
  	jk_log(pl, JK_LOG_DEBUG, "---> remote_addr: %s\n", ps->remote_addr);
      }
      if(ps->remote_host) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        4, 
                                        (*env)->NewStringUTF(env, ps->remote_host));
  	jk_log(pl, JK_LOG_DEBUG, "---> remote_host: %s\n", ps->remote_host);
      }
      if(ps->server_name) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        5, 
                                        (*env)->NewStringUTF(env, ps->server_name));
  	jk_log(pl, JK_LOG_DEBUG, "---> server_name: %s\n", ps->server_name);
      }
  
      (*env)->SetObjectArrayElement(env, 
                                    envbuf, 
                                    6, 
                                    (*env)->NewStringUTF(env, port));
      jk_log(pl, JK_LOG_DEBUG, "---> server_port: %s\n", port);
  
      if(ps->auth_type) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        7, 
                                        (*env)->NewStringUTF(env, ps->auth_type));
  	jk_log(pl, JK_LOG_DEBUG, "---> auth_type: %s\n", ps->auth_type);
      }
      if(ps->remote_user) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        8, 
                                        (*env)->NewStringUTF(env, ps->remote_user));
  	jk_log(pl, JK_LOG_DEBUG, "---> remote_user: %s\n", ps->remote_user);
      }
      if(ps->is_ssl) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        9, 
                                        (*env)->NewStringUTF(env, "https"));
      } else {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        9, 
                                        (*env)->NewStringUTF(env, "http"));
      }
      jk_log(pl, JK_LOG_DEBUG, "---> is_ssl: %s\n", ps->is_ssl ? "yes" : "no");
  
      if(ps->protocol) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        10, 
                                        (*env)->NewStringUTF(env, ps->protocol));
          jk_log(pl, JK_LOG_DEBUG, "---> protocol: %s\n", ps->protocol);
      }
      if(ps->server_software) {
          (*env)->SetObjectArrayElement(env, 
                                        envbuf, 
                                        11, 
                                        (*env)->NewStringUTF(env, ps->server_software));
          jk_log(pl, JK_LOG_DEBUG, "---> server_software: %s\n", ps->server_software);
      }
      if(ps->is_ssl) {
          if(ps->ssl_cert) {
              (*env)->SetObjectArrayElement(env, 
                                            envbuf, 
                                            12, 
                                            (*env)->NewStringUTF(env, ps->ssl_cert));
              jk_log(pl, JK_LOG_DEBUG, "---> ssl_cert: %s\n", ps->ssl_cert);
          }
          
          if(ps->ssl_cipher) {
              (*env)->SetObjectArrayElement(env, 
                                            envbuf, 
                                            13, 
                                            (*env)->NewStringUTF(env, ps->ssl_cipher));
              jk_log(pl, JK_LOG_DEBUG, "---> ssl_cipher: %s\n", ps->ssl_cipher);
          }
  
          if(ps->ssl_session) {
              (*env)->SetObjectArrayElement(env, 
                                            envbuf, 
                                            14, 
                                            (*env)->NewStringUTF(env, ps->ssl_session));
              jk_log(pl, JK_LOG_DEBUG, "---> ssl_session: %s\n", ps->ssl_session);
          }
      }
  
      jk_log(pl, JK_LOG_DEBUG, 
             "Done JNIConnectionHandler::readEnvironment\n");
  
  
      return JK_TRUE;
  }
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    readHeaders
   * Signature: (JJ[Ljava/lang/String;[Ljava/lang/String;)I
   */
  JNIEXPORT jint JNICALL 
  Java_org_apache_tomcat_service_connector_JNIConnectionHandler_readHeaders
    (JNIEnv *env, jobject o, jlong s, jlong l, jobjectArray hnames, jobjectArray hvalues)
  {
      jk_ws_service_t *ps = (jk_ws_service_t *)(int)s;
      jk_logger_t *pl = (jk_logger_t *)(int)l;
      unsigned i;
  
      jk_log(pl, JK_LOG_DEBUG, "Into JNIConnectionHandler::readHeaders\n");
  
      if(!ps) {
          jk_log(pl, JK_LOG_ERROR, 
             "In JNIConnectionHandler::readHeaders, NULL ws service object\n");
  	   return JK_FALSE;
      }
  
      jk_log(pl, JK_LOG_DEBUG, "In JNIConnectionHandler::readHeaders, %d headers follow --->\n",
  	   ps->num_headers);
  
      for(i = 0 ; i < ps->num_headers ; i++) {
          (*env)->SetObjectArrayElement(env, 
                                        hnames, 
                                        i, 
                                        (*env)->NewStringUTF(env, ps->headers_names[i]));
          (*env)->SetObjectArrayElement(env, 
                                        hvalues, 
                                        i, 
                                        (*env)->NewStringUTF(env, ps->headers_values[i]));
  	jk_log(pl, JK_LOG_DEBUG, "---> %s = %s\n",
  	       ps->headers_names[i], ps->headers_values[i]);
      }
      jk_log(pl, JK_LOG_DEBUG, 
  	   "Done JNIConnectionHandler::readHeaders\n");
  
      return JK_TRUE;
  }
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    startReasponse
   * Signature: (JJILjava/lang/String;[Ljava/lang/String;[Ljava/lang/String;I)I
   */
  JNIEXPORT jint JNICALL 
  Java_org_apache_tomcat_service_connector_JNIConnectionHandler_startReasponse
    (JNIEnv *env, jobject o, jlong s, jlong l, 
     jint sc, jstring msg, jobjectArray hnames, jobjectArray hvalues, jint hcnt)
  {
      jk_ws_service_t *ps = (jk_ws_service_t *)(int)s;
      jk_logger_t *pl = (jk_logger_t *)(int)l;
      const char *nmsg = NULL;
      char **nhnames = NULL;
      char **nhvalues = NULL;
      jstring *shnames = NULL;
      jstring *shvalues = NULL;
      int i = 0;
      int ok = JK_TRUE;
  
      jk_log(pl, JK_LOG_DEBUG, "Into JNIConnectionHandler::startReasponse\n");
  
      if(!ps) {
          jk_log(pl, JK_LOG_ERROR, 
  	       "In JNIConnectionHandler::startReasponse, NULL ws service object\n");
  	return JK_FALSE;
      }
  
      jk_log(pl, JK_LOG_DEBUG, "In JNIConnectionHandler::startReasponse, %d headers follow --->\n",
  	   hcnt);
  
      if(hcnt) {
          ok = JK_FALSE;
  
          nhnames = (char **)jk_pool_alloc(ps->pool, hcnt * sizeof(char *));
          nhvalues = (char **)jk_pool_alloc(ps->pool, hcnt * sizeof(char *));            
          shnames = (jstring *)jk_pool_alloc(ps->pool, hcnt * sizeof(jstring));
          shvalues = (jstring *)jk_pool_alloc(ps->pool, hcnt * sizeof(jstring));
  
          if(nhvalues && nhnames && shnames && shnames) {	    
              for( ; i < hcnt ; i++) {
                  jboolean iscommit;
  
                  shvalues[i] = shnames[i] = NULL;
                  nhnames[i] = nhvalues[i] = NULL;
  
                  shnames[i] = (*env)->GetObjectArrayElement(env, hnames, i);
                  shvalues[i] = (*env)->GetObjectArrayElement(env, hvalues, i);
  
                  if(!shvalues[i] || !shnames[i]) {
                      jk_log(pl, JK_LOG_ERROR, 
                             "In JNIConnectionHandler::startReasponse, GetObjectArrayElement error\n");
                      break;
                  }
  
                  nhnames[i] = (char *)(*env)->GetStringUTFChars(env, shnames[i], &iscommit);
                  nhvalues[i] = (char *)(*env)->GetStringUTFChars(env, shvalues[i], &iscommit);
  
                  if(!nhvalues[i] || !nhnames[i]) {
                      jk_log(pl, JK_LOG_ERROR, 
                             "In JNIConnectionHandler::startReasponse, GetStringUTFChars error\n");
                      break;
                  }
  		
  		jk_log(pl, JK_LOG_DEBUG, "---> %s=%s\n", nhnames[i], nhvalues[i]);	
              }
              if(i == hcnt) {
                  ok = JK_TRUE;
  		jk_log(pl, JK_LOG_DEBUG, 
                         "In JNIConnectionHandler::startReasponse. ----- End headers.\n", hcnt);
              }
  	} else {
  	    jk_log(pl, JK_LOG_ERROR,
  	           "In JNIConnectionHandler::startReasponse, memory allocation error\n");
  	}
      }			        
  
      if(msg && ok) {
          jboolean iscommit;
          nmsg = (*env)->GetStringUTFChars(env, msg, &iscommit);
          if(!nmsg) {
              ok = JK_FALSE;
          }
      }
  
      if(ok) {
          if(!ps->start_response(ps, sc, nmsg, (const char**)nhnames, (const char**)nhvalues, hcnt)) {
              ok = JK_FALSE;
              jk_log(pl, JK_LOG_ERROR, 
                     "In JNIConnectionHandler::startReasponse, servers startReasponse failed\n");
          }
      }
  
      if(nmsg) {
          (*env)->ReleaseStringUTFChars(env, msg, nmsg);
      }
          
      if(i < hcnt) {
          i++;
      }
  
      if(nhvalues) {
          int j;
  
          for(j = 0 ; j < i ; j++) {
              if(nhvalues[j]) {
                  (*env)->ReleaseStringUTFChars(env, shvalues[j], nhvalues[j]);
              }
          }
      }
  
      if(nhnames) {
          int j;
  
          for(j = 0 ; j < i ; j++) {
              if(nhnames[j]) {
                  (*env)->ReleaseStringUTFChars(env, shnames[j], nhnames[j]);
              }
          }
      }
      jk_log(pl, JK_LOG_DEBUG, "Done JNIConnectionHandler::startReasponse.\n");
  
      return ok;
  }
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    write
   * Signature: (JJ[BII)I
   */
  JNIEXPORT jint JNICALL 
  Java_org_apache_tomcat_service_connector_JNIConnectionHandler_write
    (JNIEnv *env, jobject o, jlong s, jlong l, jbyteArray buf, jint from, jint cnt)
  {
      jk_ws_service_t *ps = (jk_ws_service_t *)(int)s;
      jk_logger_t *pl = (jk_logger_t *)(int)l;
      jint rc = JK_FALSE;   
      jboolean iscommit;
      jbyte *nbuf;
      unsigned nfrom = (unsigned)from;
      unsigned ncnt = (unsigned)cnt;
  
      jk_log(pl, JK_LOG_DEBUG, 
             "In JNIConnectionHandler::write\n");
  
      if(!ps) {
      	jk_log(pl, JK_LOG_ERROR, 
  	    "In JNIConnectionHandler::write, NULL ws service object\n");
  	return JK_FALSE;
      }
      
      nbuf = (*env)->GetByteArrayElements(env, buf, &iscommit);
  
      if(!nbuf) {
          jk_log(pl, JK_LOG_ERROR, 
                 "In JNIConnectionHandler::write, GetByteArrayElements error\n");
  	return JK_FALSE;
      }
  
      if(!ps->write(ps, nbuf + nfrom, ncnt)) {
          jk_log(pl, JK_LOG_ERROR, 
                     "In JNIConnectionHandler::write, failed to write to the web server\n");
      } else {
          rc = (jint)JK_TRUE;
      }
  
      (*env)->ReleaseByteArrayElements(env, buf, nbuf, JNI_ABORT);
  
      return rc; 
  }
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/jni/jk_jnicb.h
  
  Index: jk_jnicb.h
  ===================================================================
  /* DO NOT EDIT THIS FILE - it is machine generated */
  #include <jni.h>
  /* Header for class org_apache_tomcat_service_connector_JNIConnectionHandler */
  
  #ifndef _Included_org_apache_tomcat_service_connector_JNIConnectionHandler
  #define _Included_org_apache_tomcat_service_connector_JNIConnectionHandler
  #ifdef __cplusplus
  extern "C" {
  #endif
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    getNumberOfHeaders
   * Signature: (JJ)I
   */
  JNIEXPORT jint JNICALL Java_org_apache_tomcat_service_connector_JNIConnectionHandler_getNumberOfHeaders
    (JNIEnv *, jobject, jlong, jlong);
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    read
   * Signature: (JJ[BII)I
   */
  JNIEXPORT jint JNICALL Java_org_apache_tomcat_service_connector_JNIConnectionHandler_read
    (JNIEnv *, jobject, jlong, jlong, jbyteArray, jint, jint);
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    readEnvironment
   * Signature: (JJ[Ljava/lang/String;)I
   */
  JNIEXPORT jint JNICALL Java_org_apache_tomcat_service_connector_JNIConnectionHandler_readEnvironment
    (JNIEnv *, jobject, jlong, jlong, jobjectArray);
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    readHeaders
   * Signature: (JJ[Ljava/lang/String;[Ljava/lang/String;)I
   */
  JNIEXPORT jint JNICALL Java_org_apache_tomcat_service_connector_JNIConnectionHandler_readHeaders
    (JNIEnv *, jobject, jlong, jlong, jobjectArray, jobjectArray);
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    startReasponse
   * Signature: (JJILjava/lang/String;[Ljava/lang/String;[Ljava/lang/String;I)I
   */
  JNIEXPORT jint JNICALL Java_org_apache_tomcat_service_connector_JNIConnectionHandler_startReasponse
    (JNIEnv *, jobject, jlong, jlong, jint, jstring, jobjectArray, jobjectArray, jint);
  
  /*
   * Class:     org_apache_tomcat_service_connector_JNIConnectionHandler
   * Method:    write
   * Signature: (JJ[BII)I
   */
  JNIEXPORT jint JNICALL Java_org_apache_tomcat_service_connector_JNIConnectionHandler_write
    (JNIEnv *, jobject, jlong, jlong, jbyteArray, jint, jint);
  
  #ifdef __cplusplus
  }
  #endif
  #endif
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/jni/jni_connect.dsp
  
  Index: jni_connect.dsp
  ===================================================================
  # Microsoft Developer Studio Project File - Name="jni_connect" - Package Owner=<4>
  # Microsoft Developer Studio Generated Build File, Format Version 6.00
  # ** DO NOT EDIT **
  
  # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
  
  CFG=jni_connect - Win32 Debug
  !MESSAGE This is not a valid makefile. To build this project using NMAKE,
  !MESSAGE use the Export Makefile command and run
  !MESSAGE 
  !MESSAGE NMAKE /f "jni_connect.mak".
  !MESSAGE 
  !MESSAGE You can specify a configuration when running NMAKE
  !MESSAGE by defining the macro CFG on the command line. For example:
  !MESSAGE 
  !MESSAGE NMAKE /f "jni_connect.mak" CFG="jni_connect - Win32 Debug"
  !MESSAGE 
  !MESSAGE Possible choices for configuration are:
  !MESSAGE 
  !MESSAGE "jni_connect - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE "jni_connect - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE 
  
  # Begin Project
  # PROP AllowPerConfigDependencies 0
  # PROP Scc_ProjName ""
  # PROP Scc_LocalPath ""
  CPP=cl.exe
  MTL=midl.exe
  RSC=rc.exe
  
  !IF  "$(CFG)" == "jni_connect - Win32 Release"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 0
  # PROP BASE Output_Dir "Release"
  # PROP BASE Intermediate_Dir "Release"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 0
  # PROP Output_Dir "release"
  # PROP Intermediate_Dir "release"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JNI_CONNECT_EXPORTS" /YX /FD /c
  # ADD CPP /nologo /MT /W3 /GX /O2 /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "..\jk" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JNI_CONNECT_EXPORTS" /YX /FD /c
  # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x409 /d "NDEBUG"
  # ADD RSC /l 0x409 /d "NDEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
  # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
  
  !ELSEIF  "$(CFG)" == "jni_connect - Win32 Debug"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 1
  # PROP BASE Output_Dir "Debug"
  # PROP BASE Intermediate_Dir "Debug"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 1
  # PROP Output_Dir "debug"
  # PROP Intermediate_Dir "debug"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JNI_CONNECT_EXPORTS" /YX /FD /GZ /c
  # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /I "..\jk" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "JNI_CONNECT_EXPORTS" /YX /FD /GZ /c
  # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x409 /d "_DEBUG"
  # ADD RSC /l 0x409 /d "_DEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
  # ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
  
  !ENDIF 
  
  # Begin Target
  
  # Name "jni_connect - Win32 Release"
  # Name "jni_connect - Win32 Debug"
  # Begin Group "Source Files"
  
  # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
  # Begin Source File
  
  SOURCE=.\jk_jnicb.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_pool.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_util.c
  # End Source File
  # End Group
  # Begin Group "Header Files"
  
  # PROP Default_Filter "h;hpp;hxx;hm;inl"
  # Begin Source File
  
  SOURCE=..\jk\jk_ajp12_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_global.h
  # End Source File
  # Begin Source File
  
  SOURCE=.\jk_jnicb.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_logger.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_pool.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_service.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\jk\jk_util.h
  # End Source File
  # End Group
  # Begin Group "Resource Files"
  
  # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
  # End Group
  # End Target
  # End Project
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/jni/jni_connect.dsw
  
  Index: jni_connect.dsw
  ===================================================================
  Microsoft Developer Studio Workspace File, Format Version 6.00
  # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
  
  ###############################################################################
  
  Project: "jni_connect"=.\jni_connect.dsp - Package Owner=<4>
  
  Package=<5>
  {{{
  }}}
  
  Package=<4>
  {{{
  }}}
  
  ###############################################################################
  
  Global:
  
  Package=<5>
  {{{
  }}}
  
  Package=<3>
  {{{
  }}}
  
  ###############################################################################
  
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/netscape/Makefile.solaris
  
  Index: Makefile.solaris
  ===================================================================
  # Defines for example NSAPI programs running under SOLARIS
  
  CC_CMD=gcc -DNET_SSL -DSOLARIS -D_REENTRANT
  LD_SHAREDCMD=ld -G
  
  all:
  prepare:
  
  OS_TYPE=solaris
  INCLUDEDIR=$(SUITSPOT_HOME)/include
  JAVA_INCLUDE=$(JAVA_HOME)/include
  
  JK_OBJS = jk_ajp12_worker.o jk_lb_worker.o jk_sockbuf.o jk_connect.o jk_map.o \
  jk_uri_worker_map.o jk_nsapi_plugin.o jk_util.o jk_jni_worker.o \
  jk_pool.o jk_worker.o
  
  INCLUDE_FLAGS=-I$(INCLUDEDIR) -I$(INCLUDEDIR)/base -I$(INCLUDEDIR)/frame -I$(JAVA_INCLUDE) -I$(JAVA_INCLUDE)/$(OS_TYPE)
  COMMON_DEFS=-DMCC_HTTPD -DXP_UNIX -DSPAPI20 -DSOLARIS -Wall
  
  
  all: nsapi_redirector.so 
  
  
  nsapi_redirector.so: $(JK_OBJS)
  	$(MAKE) prepare
  	$(LD_SHAREDCMD) $(JK_OBJS) -o nsapi_redirector.so $(EXTRA_LDDEFINES)
  
  .c.o:
  	$(CC_CMD) $(COMMON_DEFS) $(INCLUDE_FLAGS) -c $< 
  
  clean:
  	rm $(JK_OBJS)
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/netscape/jk_nsapi_plugin.c
  
  Index: jk_nsapi_plugin.c
  ===================================================================
  /*
   * Copyright (c) 1997-1999 The Java Apache Project.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *
   * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and 
   *    "Java Apache Project" must not be used to endorse or promote products 
   *    derived from this software without prior written permission.
   *
   * 5. Products derived from this software may not be called "Apache JServ"
   *    nor may "Apache" nor "Apache JServ" appear in their names without 
   *    prior written permission of the Java Apache Project.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *    
   * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Java Apache Group. For more information
   * on the Java Apache Project and the Apache JServ Servlet Engine project,
   * please see <http://java.apache.org/>.
   *
   */
  
  /***************************************************************************
   * Description: NSAPI plugin for Netscape servers                          *
   * Author:      Gal Shachor <sh...@il.ibm.com>                           *
   * Version:     $Revision: 1.1 $                                               *
   ***************************************************************************/
  
  
  #include "jk_global.h"
  #include "jk_util.h"
  #include "jk_map.h"
  #include "jk_pool.h"
  #include "jk_service.h"
  #include "jk_worker.h"
  #include "jk_ajp12_worker.h"
  
  #include "nsapi.h"
  
  #define URI_PATTERN "path"
  
  struct nsapi_private_data {
      jk_pool_t p;
      
      int request_started;
  
      pblock *pb;
      Session *sn;
      Request *rq;
  };
  typedef struct nsapi_private_data nsapi_private_data_t;
  
  static int init_on_other_thread_is_done = JK_FALSE;
  static int init_on_other_thread_is_ok = JK_FALSE;
  
  static jk_logger_t *logger = NULL;
  
  static int JK_METHOD start_response(jk_ws_service_t *s,
                                      int status,
                                      const char *reason,
                                      const char * const *header_names,
                                      const char * const *header_values,
                                      unsigned num_of_headers);
  
  static int JK_METHOD ws_read(jk_ws_service_t *s,
                               void *b,
                               unsigned l,
                               unsigned *a);
  
  static int JK_METHOD ws_write(jk_ws_service_t *s,
                                const void *b,
                                unsigned l);
  
  NSAPI_PUBLIC int jk_init(pblock *pb, 
                           Session *sn, 
                           Request *rq);
  
  NSAPI_PUBLIC void jk_term(void *p);
  
  NSAPI_PUBLIC int jk_service(pblock *pb,
                              Session *sn,
                              Request *rq);
  
  static int init_ws_service(nsapi_private_data_t *private_data,
                             jk_ws_service_t *s);
  
  static int setup_http_headers(nsapi_private_data_t *private_data,
                                jk_ws_service_t *s);
  
  static void init_workers_on_other_threads(void *init_d) 
  {
      jk_map_t *init_map = (jk_map_t *)init_d;
      if(wc_open(init_map, logger)) {
          init_on_other_thread_is_ok = JK_TRUE;
      } else {
          jk_log(logger, JK_LOG_EMERG, "In init_workers_on_other_threads, failed\n");
      }
  
      init_on_other_thread_is_done = JK_TRUE;
  }
  
  static int JK_METHOD start_response(jk_ws_service_t *s,
                                      int status,
                                      const char *reason,
                                      const char * const *header_names,
                                      const char * const *header_values,
                                      unsigned num_of_headers)
  {
      if(s && s->ws_private) {
          nsapi_private_data_t *p = s->ws_private;
          if(!p->request_started) {
              unsigned i;
  
              p->request_started = JK_TRUE;
  
              /* Remove "old" content type */
              param_free(pblock_remove("content-type", p->rq->srvhdrs));
  
              if(num_of_headers) {
                  for (i = 0 ; i < (int)num_of_headers ; i++) {
                      pblock_nvinsert(header_names[i],
                                      header_values[i],
                                      p->rq->srvhdrs);    
                  }
              } else {
                  pblock_nvinsert("content-type",
                                  "text/plain",
                                  p->rq->srvhdrs);    
              }
  
              protocol_status(p->sn,
                              p->rq,
                              status,
                              (char *)reason);
  
              protocol_start_response(p->sn, p->rq);
          }
          return JK_TRUE;
  
      }
      return JK_FALSE;
  }
  
  static int JK_METHOD ws_read(jk_ws_service_t *s,
                               void *b,
                               unsigned l,
                               unsigned *a)
  {
      if(s && s->ws_private && b && a) {
          nsapi_private_data_t *p = s->ws_private;
          
          *a = 0;
          if(l) {
              char *buf = b;
              unsigned i;
              netbuf *inbuf = p->sn->inbuf;
  
  #ifdef netbuf_getbytes
              i = netbuf_getbytes(inbuf, b, l);
              if(NETBUF_EOF == i || NETBUF_ERROR == i) {
                  return JK_FALSE;
              }
  
  #else 
              int ch;
              for(i = 0 ; i < l ; i++) {
                  ch = netbuf_getc(inbuf);           
                  /*
                   * IO_EOF is 0 (zero) which is a very reasonable byte
                   * when it comes to binary data. So we are not breaking 
                   * out of the read loop when reading it.
                   *
                   * We are protected from an infinit loop by the Java part of
                   * Tomcat.
                   */
                  if(IO_ERROR == ch) {
                      break;
                  }
  
                  buf[i] = ch;
              }
  
              if(0 == i) {
                  return JK_FALSE;
              }
  #endif
              *a = i;
  
          }
          return JK_TRUE;
      }
      return JK_FALSE;
  }
  
  static int JK_METHOD ws_write(jk_ws_service_t *s,
                                const void *b,
                                unsigned l)
  {
      if(s && s->ws_private && b) {
          nsapi_private_data_t *p = s->ws_private;
  
          if(l) {
              if(!p->request_started) {
                  start_response(s, 200, NULL, NULL, NULL, 0);
              }
  
              if(net_write(p->sn->csd, (char *)b, (int)l) == IO_ERROR) {
                  return JK_FALSE;
              }
          }
  
          return JK_TRUE;
  
      }
      return JK_FALSE;
  }
  
  NSAPI_PUBLIC int jk_init(pblock *pb, 
                           Session *sn, 
                           Request *rq)
  {
      char *worker_prp_file = pblock_findval(JK_WORKER_FILE_TAG, pb); 
      char *log_level_str = pblock_findval(JK_LOG_LEVEL_TAG, pb); 
      char *log_file = pblock_findval(JK_LOG_FILE_TAG, pb); 
  
      int rc = REQ_ABORTED;
      jk_map_t *init_map;
  
      fprintf(stderr, "In jk_init %s %s %s\n",worker_prp_file, log_level_str,  log_file);
      if(!worker_prp_file) {
          worker_prp_file = JK_WORKER_FILE_DEF;
      }
  
      if(!log_level_str) {
          log_level_str = JK_LOG_LEVEL_DEF;
      }    
      
      if(!jk_open_file_logger(&logger, log_file, 
                              jk_parse_log_level(log_level_str))) {
          logger = NULL;
      }
  
      if(map_alloc(&init_map)) {
          if(map_read_properties(init_map, worker_prp_file)) {
              int sleep_cnt;
              SYS_THREAD s;
              
              s = systhread_start(SYSTHREAD_DEFAULT_PRIORITY, 
                                  0, 
                                  init_workers_on_other_threads, 
                                  init_map);
              for(sleep_cnt = 0 ; sleep_cnt < 60 ; sleep_cnt++) {
                  systhread_sleep(1000);
                  jk_log(logger, JK_LOG_DEBUG, "jk_init, a second passed\n");
                  if(init_on_other_thread_is_done) {
                      break;
                  }
              }
  
              if(init_on_other_thread_is_done &&
                 init_on_other_thread_is_ok) {
                  magnus_atrestart(jk_term, NULL);
                  rc = REQ_PROCEED;
              }
  
  /*            if(wc_open(init_map, logger)) {
                  magnus_atrestart(jk_term, NULL);
                  rc = REQ_PROCEED;
              }
  */
          }
          
          map_free(&init_map);
      }
  
      return rc;    
  }
  
  NSAPI_PUBLIC void jk_term(void *p)
  {
      wc_close(logger);
      if(logger) {
          jk_close_file_logger(&logger);
      }
  }
  
  NSAPI_PUBLIC int jk_service(pblock *pb,
                              Session *sn,
                              Request *rq)
  {
      char *worker_name = pblock_findval(JK_WORKER_NAME_TAG, pb); 
      char *uri_pattern = pblock_findval(URI_PATTERN, pb);     
      jk_worker_t *worker;    
      int rc = REQ_ABORTED;
  
      if(uri_pattern) {
          char *uri = pblock_findval("uri", rq->reqpb);
  
          if(0 != shexp_match(uri, uri_pattern)) {
              return REQ_NOACTION;
          }        
      }
  
      if(!worker_name) {
          worker_name = JK_AJP12_WORKER_NAME;
      }
  
      worker = wc_get_worker_for_name(worker_name, logger);
      if(worker) {
          nsapi_private_data_t private_data;
          jk_ws_service_t s;
          jk_pool_atom_t buf[SMALL_POOL_SIZE];
  
          jk_open_pool(&private_data.p, buf, sizeof(buf));
  
          private_data.request_started = JK_FALSE;
          private_data.pb = pb;
          private_data.sn = sn;
          private_data.rq = rq;
  
          jk_init_ws_service(&s);
  
          s.ws_private = &private_data;
          s.pool = &private_data.p;
  
          if(init_ws_service(&private_data, &s)) {
              jk_endpoint_t *e = NULL;
              if(worker->get_endpoint(worker, &e, logger)) {                
                  int recover = JK_FALSE;
                  if(e->service(e, &s, logger, &recover)) {
                      rc = REQ_PROCEED;
                  }
                  e->done(&e, logger);
              }
          }
          jk_close_pool(&private_data.p);
      }
  
      return rc;
  }
  
  static int init_ws_service(nsapi_private_data_t *private_data,
                             jk_ws_service_t *s) 
  {
      char *tmp;
      int rc;
  
      s->jvm_route = NULL;
      s->start_response = start_response;
      s->read = ws_read;
      s->write = ws_write;
      
      s->auth_type        = pblock_findval("auth-type", private_data->rq->vars);
      s->remote_user      = pblock_findval("auth-user", private_data->rq->vars);
  
      s->content_length   = 0;
      tmp = NULL;
      rc  = request_header("content-length", 
                           &tmp, 
                           private_data->sn, 
                           private_data->rq);
  
      if((rc != REQ_ABORTED) && tmp) {
          s->content_length = atoi(tmp);
      }
      
      s->method           = pblock_findval("method", private_data->rq->reqpb);
      s->protocol         = pblock_findval("protocol", private_data->rq->reqpb);
      
      s->remote_host      = session_dns(private_data->sn);
      s->remote_addr      = pblock_findval("ip", private_data->sn->client);
      
      s->req_uri          = pblock_findval("uri", private_data->rq->reqpb);
      s->query_string     = pblock_findval("query", private_data->rq->reqpb);
  
      s->server_name      = server_hostname;
      s->server_port      = server_portnum;
      s->server_software  = system_version();
  
  
      s->headers_names    = NULL;
      s->headers_values   = NULL;
      s->num_headers      = 0;
      
      s->is_ssl           = security_active;
      if(s->is_ssl) {
          s->ssl_cert     = pblock_findval("auth-cert", private_data->rq->vars);
          if(s->ssl_cert) {
              s->ssl_cert_len = strlen(s->ssl_cert);
          }
          s->ssl_cipher   = pblock_findval("cipher", private_data->sn->client);
          s->ssl_session  = pblock_findval("ssl-id", private_data->sn->client);
      } else {
          s->ssl_cert     = NULL;
          s->ssl_cert_len = 0;
          s->ssl_cipher   = NULL;
          s->ssl_session  = NULL;
      }
  
      return setup_http_headers(private_data, s);
  }
  
  static int setup_http_headers(nsapi_private_data_t *private_data,
                                jk_ws_service_t *s) 
  {
      pblock *headers_jar = private_data->rq->headers;
      int cnt;
      int i;
  
      for(i = 0, cnt = 0 ; i < headers_jar->hsize ; i++) {
          struct pb_entry *h = headers_jar->ht[i];
          while(h && h->param) {
              cnt++;
              h = h->next;
          }
      }
  
      if(cnt) {
          s->headers_names  = jk_pool_alloc(&private_data->p, cnt * sizeof(char *));
          s->headers_values = jk_pool_alloc(&private_data->p, cnt * sizeof(char *));
  
          if(s->headers_names && s->headers_values) {            
              for(i = 0, cnt = 0 ; i < headers_jar->hsize ; i++) {
                  struct pb_entry *h = headers_jar->ht[i];
                  while(h && h->param) {
                      s->headers_names[cnt]  = h->param->name;
                      s->headers_values[cnt] = h->param->value;
                      cnt++;
                      h = h->next;
                  }
              }
              s->num_headers = cnt;
              return JK_TRUE;
          }
      } else {
          s->num_headers = cnt;
          s->headers_names  = NULL;
          s->headers_values = NULL;
          return JK_TRUE;
      }
  
      return JK_FALSE;
  }
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/netscape/nsapi.dsp
  
  Index: nsapi.dsp
  ===================================================================
  # Microsoft Developer Studio Project File - Name="nsapi" - Package Owner=<4>
  # Microsoft Developer Studio Generated Build File, Format Version 6.00
  # ** DO NOT EDIT **
  
  # TARGTYPE "Win32 (x86) Dynamic-Link Library" 0x0102
  
  CFG=nsapi - Win32 Debug
  !MESSAGE This is not a valid makefile. To build this project using NMAKE,
  !MESSAGE use the Export Makefile command and run
  !MESSAGE 
  !MESSAGE NMAKE /f "nsapi.mak".
  !MESSAGE 
  !MESSAGE You can specify a configuration when running NMAKE
  !MESSAGE by defining the macro CFG on the command line. For example:
  !MESSAGE 
  !MESSAGE NMAKE /f "nsapi.mak" CFG="nsapi - Win32 Debug"
  !MESSAGE 
  !MESSAGE Possible choices for configuration are:
  !MESSAGE 
  !MESSAGE "nsapi - Win32 Release" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE "nsapi - Win32 Debug" (based on "Win32 (x86) Dynamic-Link Library")
  !MESSAGE 
  
  # Begin Project
  # PROP AllowPerConfigDependencies 0
  # PROP Scc_ProjName ""
  # PROP Scc_LocalPath ""
  CPP=cl.exe
  MTL=midl.exe
  RSC=rc.exe
  
  !IF  "$(CFG)" == "nsapi - Win32 Release"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 0
  # PROP BASE Output_Dir "Release"
  # PROP BASE Intermediate_Dir "Release"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 0
  # PROP Output_Dir "nsapi_release"
  # PROP Intermediate_Dir "nsapi_release"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSAPI_EXPORTS" /YX /FD /c
  # ADD CPP /nologo /MT /W3 /GX /O2 /I "..\common" /I "$(NS_HOME)\include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSAPI_EXPORTS" /D "XP_WIN32" /YX /FD /c
  # ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x409 /d "NDEBUG"
  # ADD RSC /l 0x409 /d "NDEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
  # ADD LINK32 wsock32.lib ns-httpd36.lib /nologo /dll /machine:I386 /out:"nsapi_release/nsapi_redirect.dll" /libpath:"$(NS_HOME)\lib"
  
  !ELSEIF  "$(CFG)" == "nsapi - Win32 Debug"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 1
  # PROP BASE Output_Dir "nsapi___Win32_Debug"
  # PROP BASE Intermediate_Dir "nsapi___Win32_Debug"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 1
  # PROP Output_Dir "nsapi_debug"
  # PROP Intermediate_Dir "nsapi_debug"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSAPI_EXPORTS" /YX /FD /GZ /c
  # ADD CPP /nologo /MTd /W3 /Gm /GX /ZI /Od /I "..\common" /I "$(NS_HOME)\include" /I "$(JAVA_HOME)\include" /I "$(JAVA_HOME)\include\win32" /D "WIN32" /D "_DEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "NSAPI_EXPORTS" /D "XP_WIN32" /D "MCC_HTTPD" /D "SPAPI20" /YX /FD /GZ /c
  # ADD BASE MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD MTL /nologo /D "_DEBUG" /mktyplib203 /win32
  # ADD BASE RSC /l 0x409 /d "_DEBUG"
  # ADD RSC /l 0x409 /d "_DEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /debug /machine:I386 /pdbtype:sept
  # ADD LINK32 wsock32.lib ns-httpd36.lib /nologo /dll /debug /machine:I386 /out:"nsapi_debug/nsapi_redirect.dll" /pdbtype:sept /libpath:"$(NS_HOME)\lib"
  
  !ENDIF 
  
  # Begin Target
  
  # Name "nsapi - Win32 Release"
  # Name "nsapi - Win32 Debug"
  # Begin Group "Source Files"
  
  # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
  # Begin Source File
  
  SOURCE=..\common\jk_ajp12_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_connect.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_jni_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_lb_worker.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_msg_buff.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\jk_nsapi_plugin.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_pool.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_sockbuf.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_uri_worker_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_util.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker.c
  # End Source File
  # End Group
  # Begin Group "Header Files"
  
  # PROP Default_Filter "h;hpp;hxx;hm;inl"
  # Begin Source File
  
  SOURCE=..\common\jk_ajp12_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_connect.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_global.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_jni_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_lb_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_logger.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_msg_buff.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_mt.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_pool.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_service.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_sockbuf.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_uri_worker_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_util.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_worker_list.h
  # End Source File
  # End Group
  # Begin Group "Resource Files"
  
  # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
  # End Group
  # End Target
  # End Project
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/netscape/nsapi.dsw
  
  Index: nsapi.dsw
  ===================================================================
  Microsoft Developer Studio Workspace File, Format Version 6.00
  # WARNING: DO NOT EDIT OR DELETE THIS WORKSPACE FILE!
  
  ###############################################################################
  
  Project: "nsapi"=".\nsapi.dsp" - Package Owner=<4>
  
  Package=<5>
  {{{
  }}}
  
  Package=<4>
  {{{
  }}}
  
  ###############################################################################
  
  Global:
  
  Package=<5>
  {{{
  }}}
  
  Package=<3>
  {{{
  }}}
  
  ###############################################################################
  
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/nt_service/jk_nt_service.c
  
  Index: jk_nt_service.c
  ===================================================================
  /*
   * Copyright (c) 1997-1999 The Java Apache Project.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *
   * 4. The names "Apache JServ", "Apache JServ Servlet Engine" and 
   *    "Java Apache Project" must not be used to endorse or promote products 
   *    derived from this software without prior written permission.
   *
   * 5. Products derived from this software may not be called "Apache JServ"
   *    nor may "Apache" nor "Apache JServ" appear in their names without 
   *    prior written permission of the Java Apache Project.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Java Apache 
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *    
   * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Java Apache Group. For more information
   * on the Java Apache Project and the Apache JServ Servlet Engine project,
   * please see <http://java.apache.org/>.
   *
   */
  
  /***************************************************************************
   * Description: NT System service for Jakarta/Tomcat                       *
   * Author:      Gal Shachor <sh...@il.ibm.com>                           *
   * Version:     $Revision: 1.1 $                                           *
   ***************************************************************************/
  
  #include "jk_global.h"
  #include "jk_util.h"
  #include "jk_ajp13.h"
  #include "jk_connect.h"
  
  #include <windows.h>
  #include <stdio.h>
  #include <stdlib.h>
  #include <process.h>
  
  #define AJP12_TAG              ("ajp12")
  #define AJP13_TAG              ("ajp13")
  #define BASE_REGISTRY_LOCATION ("SYSTEM\\CurrentControlSet\\Services\\")
  #define IMAGE_NAME             ("ImagePath")
  #define PARAMS_LOCATION        ("Parameters")
  #define PRP_LOCATION           ("PropertyFile")
  
  // internal variables
  static SERVICE_STATUS          ssStatus;       // current status of the service
  static SERVICE_STATUS_HANDLE   sshStatusHandle;
  static DWORD                   dwErr = 0;
  static char                    szErr[1024] = "";
  static HANDLE                  hServerStopEvent = NULL;
  static int                     shutdown_port;
  static char                    *shutdown_protocol = AJP12_TAG;
  
  struct jk_tomcat_startup_data {
      char *classpath;
      char *tomcat_home;
      char *stdout_file;
      char *stderr_file;
      char *java_bin;
      char *tomcat_class;
      char *server_file;
      char *cmd_line;
      int  shutdown_port;
      char *shutdown_protocol;
  
      char *extra_path;
  };
  typedef struct jk_tomcat_startup_data jk_tomcat_startup_data_t;
  
  // internal function prototypes
  static void WINAPI service_ctrl(DWORD dwCtrlCode);
  static void WINAPI service_main(DWORD dwArgc, 
                                  char **lpszArgv);
  static void install_service(char *name, 
                              char *prp_file);
  static void remove_service(char *name);
  static char *GetLastErrorText(char *lpszBuf, DWORD dwSize);
  static void AddToMessageLog(char *lpszMsg);
  static BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
                                  DWORD dwWin32ExitCode,
                                  DWORD dwWaitHint);
  static void start_jk_service(char *name);
  static void stop_jk_service(void);
  static int set_registry_values(char *name, 
                                 char *prp_file);
  static int create_registry_key(const char *tag, 
                                 HKEY *key);
  static int set_registry_config_parameter(HKEY hkey, 
                                           const char *tag, 
                                           char *value);
  static int get_registry_config_parameter(HKEY hkey, 
                                           const char *tag,  
                                           char *b, DWORD sz);
  static int start_tomcat(const char *name, 
                          HANDLE *hTomcat);
  static void stop_tomcat(short port, 
                          const char *protocol,
                          HANDLE hTomcat);
  static int read_startup_data(jk_map_t *init_map, 
                               jk_tomcat_startup_data_t *data, 
                               jk_pool_t *p);
  
  
  static void usage_message(const char *name)
  {
      printf("%s - Usage:\n", name);
      printf("%s -i <service name> <configuration properties file>\n", name);
      printf("\tto install the service\n");
      printf("%s -r <service name>\n", name);    
      printf("\tto remove the service\n");
  }
  
  void main(int argc, char **argv)
  {
      WORD wVersionRequested;
      WSADATA wsaData;
      int err; 
          
      wVersionRequested = MAKEWORD(1, 1); 
      err = WSAStartup(wVersionRequested, &wsaData);
      if(0 != err) {
          fprintf(stderr, "Error connecting to winosck");
          return;
      } 
  
      if(LOBYTE( wsaData.wVersion ) != 1 || 
         HIBYTE( wsaData.wVersion ) != 1)  {
          fprintf(stderr, 
                  "Error winsock version is %d %d \n", 
                  LOBYTE( wsaData.wVersion ),HIBYTE( wsaData.wVersion ));
          WSACleanup();
          return; 
      } 
  
      fprintf(stderr, "Asked (and given) winsock %d.%d \n", 
                      LOBYTE(wsaData.wVersion),
                      HIBYTE(wsaData.wVersion));
  
  
      __try {
          if((argc > 2) && ((*argv[1] == '-') || (*argv[1] == '/'))) {
              char *cmd = argv[1];
              cmd++;
              if(0 == stricmp("i", cmd) && (4 == argc)) {
                  install_service(argv[2], argv[3]);
                  return;
              } else if(0 == stricmp("r", cmd) && (3 == argc)) {
                  remove_service(argv[2]);
                  return;
              } else if(0 == stricmp("s", cmd) && (3 == argc)) {
                  HANDLE hTomcat;
                  start_tomcat(argv[2], &hTomcat);
                  return;
              }
          } else if(2  == argc) {
  
              SERVICE_TABLE_ENTRY dispatchTable[] =
              {
                  { argv[1], (LPSERVICE_MAIN_FUNCTION)service_main },
                  { NULL, NULL }
              };
  
              if(!StartServiceCtrlDispatcher(dispatchTable)) {
                  AddToMessageLog("StartServiceCtrlDispatcher failed.");
              }
              return;
          } 
  
          usage_message(argv[0]);
          exit(-1);
      } __finally {
          WSACleanup();
      }
  }
  
  void WINAPI service_main(DWORD dwArgc, char **lpszArgv)
  {
      // register our service control handler:
      //
      //
      sshStatusHandle = RegisterServiceCtrlHandler(lpszArgv[0], service_ctrl);
  
      if(sshStatusHandle) {
  
          ssStatus.dwServiceType = SERVICE_WIN32_OWN_PROCESS;
          ssStatus.dwServiceSpecificExitCode = 0;
  
          // report the status to the service control manager.
          //
          if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
                                  NO_ERROR,              // exit code
                                  3000)) {                 // wait hint    
              start_jk_service(lpszArgv[0]);
          }
      }
  
      // try to report the stopped status to the service control manager.
      //
      if(sshStatusHandle) {
          ReportStatusToSCMgr(SERVICE_STOPPED,
                              dwErr,
                              0);
      }
  }
  
  
  void WINAPI service_ctrl(DWORD dwCtrlCode)
  {
      /*
       * Handle the requested control code.
       */
      switch(dwCtrlCode)
      {
          /*
           * Stop the service.
           */
          case SERVICE_CONTROL_STOP:
              ssStatus.dwCurrentState = SERVICE_STOP_PENDING;
              stop_jk_service();
              break;
  
          /*
           * Update the service status.
           */
          case SERVICE_CONTROL_INTERROGATE:
              break;
  
          /*
           * Invalid control code, nothing to do.
           */
          default:
              break;
  
      }
  
      ReportStatusToSCMgr(ssStatus.dwCurrentState, NO_ERROR, 0);
  
  }
  
  BOOL ReportStatusToSCMgr(DWORD dwCurrentState,
                           DWORD dwWin32ExitCode,
                           DWORD dwWaitHint)
  {
      static DWORD dwCheckPoint = 1;
      BOOL fResult = TRUE;
  
      if(dwCurrentState == SERVICE_START_PENDING) {
          ssStatus.dwControlsAccepted = 0;
      } else {
          ssStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP;
      }
  
      ssStatus.dwCurrentState = dwCurrentState;
      ssStatus.dwWin32ExitCode = dwWin32ExitCode;
      ssStatus.dwWaitHint = dwWaitHint;
  
      if((dwCurrentState == SERVICE_RUNNING) ||
         (dwCurrentState == SERVICE_STOPPED)) {
          ssStatus.dwCheckPoint = 0;
      } else {
          ssStatus.dwCheckPoint = dwCheckPoint++;
      }
  
      if(!(fResult = SetServiceStatus(sshStatusHandle, &ssStatus))) {
          AddToMessageLog(TEXT("SetServiceStatus"));
      }
  
      return fResult;
  }
  
  void install_service(char *name, 
                       char *rel_prp_file)
  {
      SC_HANDLE   schService;
      SC_HANDLE   schSCManager;
      char        szExecPath[2048];
      char        szPropPath[2048];
      char        *dummy;
  
      if(!GetFullPathName(rel_prp_file, sizeof(szPropPath) - 1, szPropPath, &dummy)) {
          printf("Unable to install %s - %s\n", 
                 name, 
                 GetLastErrorText(szErr, sizeof(szErr)));
          return;
      }
  
      if(!jk_file_exists(szPropPath)) {
          printf("Unable to install %s - File [%s] does not exists\n", 
                 name, 
                 szPropPath);
          return;
      }
  
      if(GetModuleFileName( NULL, szExecPath, sizeof(szExecPath) - 1) == 0) {
          printf("Unable to install %s - %s\n", 
                 name, 
                 GetLastErrorText(szErr, sizeof(szErr)));
          return;
      }
  
      schSCManager = OpenSCManager(NULL,  // machine (NULL == local)
                                   NULL,  // database (NULL == default)
                                   SC_MANAGER_ALL_ACCESS);   // access required                       
      if(schSCManager) {
          schService = CreateService(schSCManager, // SCManager database
                                     name,         // name of service
                                     name,         // name to display
                                     SERVICE_ALL_ACCESS, // desired access
                                     SERVICE_WIN32_OWN_PROCESS,  // service type
                                     SERVICE_DEMAND_START,       // start type
                                     SERVICE_ERROR_NORMAL,       // error control type
                                     szExecPath,                 // service's binary
                                     NULL,                       // no load ordering group
                                     NULL,                       // no tag identifier
                                     NULL,                       // dependencies
                                     NULL,                       // LocalSystem account
                                     NULL);                      // no password
  
          if(schService) {
              printf("The service named %s was created. Now adding registry entries\n", name);
              
              if(set_registry_values(name, szPropPath)) {
                  CloseServiceHandle(schService);
              } else {
                  printf("CreateService failed setting the private registry - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
                  DeleteService(schService);
                  CloseServiceHandle(schService);
              }
          } else {
              printf("CreateService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
          }
  
          CloseServiceHandle(schSCManager);
      } else { 
          printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
      }
  }
  
  void remove_service(char *name)
  {
      SC_HANDLE   schService;
      SC_HANDLE   schSCManager;
  
      schSCManager = OpenSCManager(NULL,          // machine (NULL == local)
                                   NULL,          // database (NULL == default)
                                   SC_MANAGER_ALL_ACCESS );  // access required
                          
      if(schSCManager) {
          schService = OpenService(schSCManager, name, SERVICE_ALL_ACCESS);
  
          if(schService) {
              // try to stop the service
              if(ControlService( schService, SERVICE_CONTROL_STOP, &ssStatus )) {
                  printf("Stopping %s.", name);
                  Sleep(1000);
  
                  while(QueryServiceStatus(schService, &ssStatus )) {
                      if(ssStatus.dwCurrentState == SERVICE_STOP_PENDING) {
                          printf(".");
                          Sleep(1000);
                      } else {
                          break;
                      }
                  }
  
                  if(ssStatus.dwCurrentState == SERVICE_STOPPED) {
                      printf("\n%s stopped.\n", name);
                  } else {
                      printf("\n%s failed to stop.\n", name);
                  }
              }
  
              // now remove the service
              if(DeleteService(schService)) {
                  printf("%s removed.\n", name);
              } else {
                  printf("DeleteService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
              }
  
              CloseServiceHandle(schService);
          } else {
              printf("OpenService failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
          }
  
          CloseServiceHandle(schSCManager);
      } else {
          printf("OpenSCManager failed - %s\n", GetLastErrorText(szErr, sizeof(szErr)));
      }
  }
  
  static int set_registry_values(char *name, 
                                 char *prp_file)
  {
      char  tag[1024];
      HKEY  hk;
      int rc;
  
      strcpy(tag, BASE_REGISTRY_LOCATION);
      strcat(tag, name);
      strcat(tag, "\\");
      strcat(tag, PARAMS_LOCATION);
  
      rc = create_registry_key(tag, &hk);
  
      if(rc) {
          rc = set_registry_config_parameter(hk, PRP_LOCATION, prp_file);
          if(!rc) {
              printf("Error: Can not create value [%s] - %s\n", 
                      PRP_LOCATION, 
                      GetLastErrorText(szErr, sizeof(szErr)));                
          }
          RegCloseKey(hk);
      } else {
          printf("Error: Can not create key [%s] - %s\n", 
                  tag, 
                  GetLastErrorText(szErr, sizeof(szErr)));                
      }
  
      if(rc) {
          char value[2024];
  
          rc = JK_FALSE;
  
          strcpy(tag, BASE_REGISTRY_LOCATION);
          strcat(tag, name);
          
          if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                                           tag,
                                           (DWORD)0,         
                                           KEY_WRITE | KEY_READ,
                                           &hk)) {
              rc = get_registry_config_parameter(hk,
                                                 IMAGE_NAME, 
                                                 value,
                                                 sizeof(value));
              if(rc) {
                  strcat(value, " ");
                  strcat(value, name);
                  rc = set_registry_config_parameter(hk,
                                                     IMAGE_NAME, 
                                                     value);
                  if(rc) {
                      printf("Registry values were added\n");
                      printf("If you have already updated wrapper.properties you may start the %s service by executing \"net start %s\" from the command prompt\n",
                             name,
                             name);                    
                  }
              }
              RegCloseKey(hk);
          }
          if(!rc) {
              printf("Error: Failed to update the service command line - %s\n", 
                      GetLastErrorText(szErr, sizeof(szErr)));                
          }
      }
  
      return rc;
  }
  
  static void start_jk_service(char *name)
  {
      /*
       * report the status to the service control manager.
       */
      if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
                             NO_ERROR,              // exit code
                             3000)) {               // wait hint
          
          /* 
           * create the event object. The control handler function signals
           * this event when it receives the "stop" control code.
           */
          hServerStopEvent = CreateEvent(NULL,    // no security attributes
                                         TRUE,    // manual reset event
                                         FALSE,   // not-signalled
                                         NULL);   // no name
  
          if(hServerStopEvent) {
              if(ReportStatusToSCMgr(SERVICE_START_PENDING, // service state
                                     NO_ERROR,              // exit code
                                     20000)) {              // wait hint
                  HANDLE hTomcat = NULL;
                  int rc = start_tomcat(name, &hTomcat);
  
                  if(rc && ReportStatusToSCMgr(SERVICE_RUNNING, // service state
                                               NO_ERROR,        // exit code
                                               0)) {            // wait hint       
                      HANDLE waitfor[] = { hServerStopEvent, hTomcat};
                      DWORD dwIndex = WaitForMultipleObjects(2, waitfor, FALSE, INFINITE);
  
                      switch(dwIndex) {
                      case WAIT_OBJECT_0:
                          /* 
                           * Stop order arrived 
                           */ 
                          ResetEvent(hServerStopEvent);
                          stop_tomcat((short)shutdown_port, shutdown_protocol, hTomcat);
                          break;
                      case (WAIT_OBJECT_0 + 1):
                          /* 
                           * Tomcat died !!!
                           */ 
                          break;
                      default:
                          /* 
                           * some error... 
                           * close the servlet container and exit 
                           */ 
                          stop_tomcat((short)shutdown_port, shutdown_protocol, hTomcat);
                      }
                      CloseHandle(hServerStopEvent);
                      CloseHandle(hTomcat);
                  }                
              }
          }
      }
  
      if(hServerStopEvent) {
          CloseHandle(hServerStopEvent);
      }
  }
  
  
  static void stop_jk_service(void)
  {
      if(hServerStopEvent) {
          SetEvent(hServerStopEvent);
      }
  }
  
  static void AddToMessageLog(char *lpszMsg)
  {   
      char    szMsg[2048];
      HANDLE  hEventSource;
      char *  lpszStrings[2];
  
      printf("Error: %s\n", lpszMsg);
  
      dwErr = GetLastError();
  
      hEventSource = RegisterEventSource(NULL, "Jakrta - Tomcat");
  
      sprintf(szMsg, "%s error: %d", "Jakrta - Tomcat", dwErr);
      lpszStrings[0] = szMsg;
      lpszStrings[1] = lpszMsg;
  
      if(hEventSource != NULL) {
          ReportEvent(hEventSource, // handle of event source
              EVENTLOG_ERROR_TYPE,  // event type
              0,                    // event category
              0,                    // event ID
              NULL,                 // current user's SID
              2,                    // strings in lpszStrings
              0,                    // no bytes of raw data
              lpszStrings,          // array of error strings
              NULL);                // no raw data
  
          DeregisterEventSource(hEventSource);
      }
      
  }
  
  //
  //  FUNCTION: GetLastErrorText
  //
  //  PURPOSE: copies error message text to string
  //
  //  PARAMETERS:
  //    lpszBuf - destination buffer
  //    dwSize - size of buffer
  //
  //  RETURN VALUE:
  //    destination buffer
  //
  //  COMMENTS:
  //
  char *GetLastErrorText( char *lpszBuf, DWORD dwSize )
  {
      DWORD dwRet;
      char *lpszTemp = NULL;
  
      dwRet = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM |FORMAT_MESSAGE_ARGUMENT_ARRAY,
                            NULL,
                            GetLastError(),
                            LANG_NEUTRAL,
                            (char *)&lpszTemp,
                            0,
                            NULL);
  
      // supplied buffer is not long enough
      if(!dwRet || ((long)dwSize < (long)dwRet+14)) {
          lpszBuf[0] = '\0';
      } else {
          lpszTemp[lstrlen(lpszTemp)-2] = '\0';  //remove cr and newline character
          sprintf(lpszBuf, "%s (0x%x)", lpszTemp, GetLastError());
      }
  
      if(lpszTemp) {
          LocalFree((HLOCAL) lpszTemp );
      }
  
      return lpszBuf;
  }
  
  static void stop_tomcat(short port, 
                          const char *protocol,
                          HANDLE hTomcat)
  {
      struct sockaddr_in in;
      
      if(jk_resolve("localhost", port, &in)) {
          int sd = jk_open_socket(&in, JK_TRUE, NULL);
          if(sd >0) {
              int rc = JK_FALSE;
              if(!strcasecmp(protocol, "ajp13")) {
                  jk_pool_t pool;
                  jk_msg_buf_t *msg = NULL;
                  jk_pool_atom_t buf[TINY_POOL_SIZE];
  
                  jk_open_pool(&pool, buf, sizeof(buf));
  
                  msg = jk_b_new(&pool);
                  jk_b_set_buffer_size(msg, 512); 
  
                  rc = ajp13_marshal_shutdown_into_msgb(msg, 
                                                        &pool,
                                                        NULL);
                  if(rc) {
                      jk_b_end(msg);
      
                      if(0 > jk_tcp_socket_sendfull(sd, 
                                                    jk_b_get_buff(msg),
                                                    jk_b_get_len(msg))) {
                          rc = JK_FALSE;
                      }
                  }                                                    
              } else {
                  char b[] = {(char)254, (char)15};
                  int rc = send(sd, b, 2, 0);
                  if(2 == rc) {
                      rc = JK_TRUE;
                  }
              }
              jk_close_socket(sd);
              if(2 == rc) {
                  if(WAIT_OBJECT_0 == WaitForSingleObject(hTomcat, 30*1000)) {
                      return;
                  }
              }            
          }
      }
  
      TerminateProcess(hTomcat, 0);    
  }
  
  static int start_tomcat(const char *name, HANDLE *hTomcat)
  {
      char  tag[1024];
      HKEY  hk;
  
      strcpy(tag, BASE_REGISTRY_LOCATION);
      strcat(tag, name);
      strcat(tag, "\\");
      strcat(tag, PARAMS_LOCATION);
  
      if(ERROR_SUCCESS == RegOpenKeyEx(HKEY_LOCAL_MACHINE,
                                       tag,
                                       (DWORD)0,         
                                       KEY_READ,
                                       &hk)) {
          char prp_file[2048];
          if(get_registry_config_parameter(hk,
                                           PRP_LOCATION, 
                                           prp_file,
                                           sizeof(prp_file))) {
              jk_map_t *init_map;
              
              if(map_alloc(&init_map)) {
                  if(map_read_properties(init_map, prp_file)) {
                      jk_tomcat_startup_data_t data;
                      jk_pool_t p;
                      jk_pool_atom_t buf[HUGE_POOL_SIZE];
                      jk_open_pool(&p, buf, sizeof(buf));
              
                      if(read_startup_data(init_map, &data, &p)) {
                          STARTUPINFO startupInfo;
                          PROCESS_INFORMATION processInformation;
                          SECURITY_ATTRIBUTES sa = { sizeof(SECURITY_ATTRIBUTES), NULL, TRUE };
  
                          if(data.extra_path) {
                              jk_append_libpath(&p, data.extra_path);
                          }
  
                          memset(&startupInfo, 0, sizeof(startupInfo));
                          startupInfo.cb = sizeof(startupInfo);
                          startupInfo.lpTitle = "Jakarta Tomcat";
                          startupInfo.dwFlags = STARTF_USESTDHANDLES;
                          startupInfo.hStdInput = NULL;
                          startupInfo.hStdOutput = CreateFile(data.stdout_file,
                                                              GENERIC_WRITE,
                                                              FILE_SHARE_READ,
                                                              &sa,
                                                              OPEN_ALWAYS,
                                                              FILE_ATTRIBUTE_NORMAL,
                                                              NULL);
                          startupInfo.hStdError = CreateFile(data.stderr_file,
                                                             GENERIC_WRITE,
                                                             FILE_SHARE_READ,
                                                             &sa,
                                                             OPEN_ALWAYS,
                                                             FILE_ATTRIBUTE_NORMAL,
                                                             NULL);
  
                          memset(&processInformation, 0, sizeof(processInformation));
                          
                          printf(data.cmd_line);
                          if(CreateProcess(data.java_bin,
                                          data.cmd_line,
                                          NULL,
                                          NULL,
                                          TRUE,
                                          CREATE_NEW_CONSOLE,
                                          NULL,
                                          data.tomcat_home,
                                          &startupInfo,
                                          &processInformation)){
  
                              *hTomcat = processInformation.hProcess;
                              CloseHandle(processInformation.hThread);
                              CloseHandle(startupInfo.hStdOutput);
                              CloseHandle(startupInfo.hStdError);
                              shutdown_port = data.shutdown_port;
                              shutdown_protocol = strdup(data.shutdown_protocol);
  
                              return JK_TRUE;
                          } else {
                              printf("Error: Can not create new process - %s\n", 
                                      GetLastErrorText(szErr, sizeof(szErr)));                
                          }
  
                      }                    
                  }
              }
              map_free(&init_map);
          }
          RegCloseKey(hk);
      } 
  
      return JK_FALSE;
  }
  
  static int create_registry_key(const char *tag,
                                 HKEY *key)
  {
      LONG  lrc = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
                                 tag,
  			                   0,
  			                   NULL,
  			                   REG_OPTION_NON_VOLATILE,
  			                   KEY_WRITE,
  			                   NULL,
  			                   key,
  			                   NULL);
      if(ERROR_SUCCESS != lrc) {
          return JK_FALSE;        
      }
  
      return JK_TRUE;
  }
  
  static int set_registry_config_parameter(HKEY hkey,
                                           const char *tag, 
                                           char *value)
  {       
      LONG  lrc;
  
      lrc = RegSetValueEx(hkey, 
                          tag,            
  			            0,              
  			            REG_SZ,  
      			        value, 
                          strlen(value));
  
      if(ERROR_SUCCESS != lrc) {
          return JK_FALSE;        
      }
  
      return JK_TRUE;     
  }
  
  
  
  static int get_registry_config_parameter(HKEY hkey,
                                           const char *tag, 
                                           char *b,
                                           DWORD sz)
  {   
      DWORD type = 0;
      LONG  lrc;
  
      lrc = RegQueryValueEx(hkey,     
                            tag,      
                            (LPDWORD)0,
                            &type,    
                            (LPBYTE)b,
                            &sz); 
      if(ERROR_SUCCESS != lrc) {
          return JK_FALSE;        
      }
      
      b[sz] = '\0';
  
      return JK_TRUE;     
  }
  
  static int read_startup_data(jk_map_t *init_map, 
                               jk_tomcat_startup_data_t *data, 
                               jk_pool_t *p)
  {
      
      data->classpath = NULL;
      data->tomcat_home = NULL;
      data->stdout_file = NULL;
      data->stderr_file = NULL;
      data->java_bin = NULL;
      data->extra_path = NULL;
      data->tomcat_class = NULL;
      data->server_file = NULL;
  
      data->server_file = map_get_string(init_map, 
                                         "wrapper.server_xml", 
                                         NULL);
      if(!data->server_file) {
          return JK_FALSE;
      }
  
      data->classpath = map_get_string(init_map, 
                                       "wrapper.class_path", 
                                         NULL);
      if(!data->classpath) {
          return JK_FALSE;
      }
  
      data->tomcat_home = map_get_string(init_map, 
                                         "wrapper.tomcat_home", 
                                         NULL);
      if(!data->tomcat_home) {
          return JK_FALSE;
      }
  
      data->java_bin = map_get_string(init_map, 
                                      "wrapper.javabin", 
                                      NULL);
      if(!data->java_bin) {
          return JK_FALSE;
      }
  
      data->tomcat_class = map_get_string(init_map,
                                          "wrapper.startup_class",
                                          "org.apache.tomcat.startup.Tomcat");
  
      if(NULL == data->tomcat_class) {
          return JK_FALSE;
      }
  
      data->cmd_line = map_get_string(init_map,
                                      "wrapper.cmd_line",
                                      NULL);
      if(NULL == data->cmd_line) {
          data->cmd_line = (char *)jk_pool_alloc(p, (20 + 
                                                     strlen(data->java_bin) +
                                                     strlen(" -classpath ") +
                                                     strlen(data->classpath) +
                                                     strlen(data->tomcat_class) +
                                                     strlen(" -home ") +
                                                     strlen(data->tomcat_home) +
                                                     strlen(" -config ") +
                                                     strlen(data->server_file)
                                                     ) * sizeof(char));
          if(NULL == data->cmd_line) {
              return JK_FALSE;
          }
  
          strcpy(data->cmd_line, data->java_bin);
          strcat(data->cmd_line, " -classpath ");
          strcat(data->cmd_line, data->classpath);
          strcat(data->cmd_line, " ");
          strcat(data->cmd_line, data->tomcat_class);
          strcat(data->cmd_line, " -home ");
          strcat(data->cmd_line, data->tomcat_home);
          strcat(data->cmd_line, " -config ");
          strcat(data->cmd_line, data->server_file);
      }
  
      data->shutdown_port = map_get_int(init_map,
                                        "wrapper.shutdown_port",
                                        8007);
  
      data->shutdown_protocol = map_get_string(init_map,
                                               "wrapper.shutdown_protocol",
                                               AJP12_TAG);
  
      data->extra_path = map_get_string(init_map,
                                        "wrapper.ld_path",
                                        NULL);
  
      data->stdout_file = map_get_string(init_map,
                                         "wrapper.stdout",
                                         NULL);
  
      if(NULL == data->stdout_file) {
          data->stdout_file = jk_pool_alloc(p, strlen(data->tomcat_home) + 2 + strlen("\\stdout.log"));
          strcpy(data->stdout_file, data->tomcat_home);
          strcat(data->stdout_file, "\\stdout.log");        
      }
  
      data->stderr_file = map_get_string(init_map,
                                         "wrapper.stderr",
                                         NULL);
  
      if(NULL == data->stderr_file) {
          data->stderr_file = jk_pool_alloc(p, strlen(data->tomcat_home) + 2 + strlen("\\stderr.log"));
          strcpy(data->stderr_file, data->tomcat_home);
          strcat(data->stderr_file, "\\stderr.log");        
      }
  
      return JK_TRUE;
  }
  
  
  
  
  1.1                  jakarta-tomcat/src/native/mod_jk/nt_service/nt_service.dsp
  
  Index: nt_service.dsp
  ===================================================================
  # Microsoft Developer Studio Project File - Name="nt_service" - Package Owner=<4>
  # Microsoft Developer Studio Generated Build File, Format Version 6.00
  # ** DO NOT EDIT **
  
  # TARGTYPE "Win32 (x86) Console Application" 0x0103
  
  CFG=nt_service - Win32 Debug
  !MESSAGE This is not a valid makefile. To build this project using NMAKE,
  !MESSAGE use the Export Makefile command and run
  !MESSAGE 
  !MESSAGE NMAKE /f "nt_service.mak".
  !MESSAGE 
  !MESSAGE You can specify a configuration when running NMAKE
  !MESSAGE by defining the macro CFG on the command line. For example:
  !MESSAGE 
  !MESSAGE NMAKE /f "nt_service.mak" CFG="nt_service - Win32 Debug"
  !MESSAGE 
  !MESSAGE Possible choices for configuration are:
  !MESSAGE 
  !MESSAGE "nt_service - Win32 Release" (based on "Win32 (x86) Console Application")
  !MESSAGE "nt_service - Win32 Debug" (based on "Win32 (x86) Console Application")
  !MESSAGE 
  
  # Begin Project
  # PROP AllowPerConfigDependencies 0
  # PROP Scc_ProjName ""
  # PROP Scc_LocalPath ""
  CPP=cl.exe
  RSC=rc.exe
  
  !IF  "$(CFG)" == "nt_service - Win32 Release"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 0
  # PROP BASE Output_Dir "Release"
  # PROP BASE Intermediate_Dir "Release"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 0
  # PROP Output_Dir "Release"
  # PROP Intermediate_Dir "Release"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
  # ADD CPP /nologo /W3 /GX /O2 /I "../jk" /D "WIN32" /D "NDEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /c
  # ADD BASE RSC /l 0x409 /d "NDEBUG"
  # ADD RSC /l 0x409 /d "NDEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386
  # ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /machine:I386 /out:"Release/jk_nt_service.exe"
  
  !ELSEIF  "$(CFG)" == "nt_service - Win32 Debug"
  
  # PROP BASE Use_MFC 0
  # PROP BASE Use_Debug_Libraries 1
  # PROP BASE Output_Dir "Debug"
  # PROP BASE Intermediate_Dir "Debug"
  # PROP BASE Target_Dir ""
  # PROP Use_MFC 0
  # PROP Use_Debug_Libraries 1
  # PROP Output_Dir "Debug"
  # PROP Intermediate_Dir "Debug"
  # PROP Ignore_Export_Lib 0
  # PROP Target_Dir ""
  # ADD BASE CPP /nologo /W3 /Gm /GX /ZI /Od /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
  # ADD CPP /nologo /W3 /Gm /GX /ZI /Od /I "../jk" /D "WIN32" /D "_DEBUG" /D "_CONSOLE" /D "_MBCS" /YX /FD /GZ /c
  # ADD BASE RSC /l 0x409 /d "_DEBUG"
  # ADD RSC /l 0x409 /d "_DEBUG"
  BSC32=bscmake.exe
  # ADD BASE BSC32 /nologo
  # ADD BSC32 /nologo
  LINK32=link.exe
  # ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /pdbtype:sept
  # ADD LINK32 wsock32.lib kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /subsystem:console /debug /machine:I386 /out:"Debug/jk_nt_service.exe" /pdbtype:sept
  
  !ENDIF 
  
  # Begin Target
  
  # Name "nt_service - Win32 Release"
  # Name "nt_service - Win32 Debug"
  # Begin Group "Source Files"
  
  # PROP Default_Filter "cpp;c;cxx;rc;def;r;odl;idl;hpj;bat"
  # Begin Source File
  
  SOURCE=..\common\jk_ajp13.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_connect.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_map.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_msg_buff.c
  # End Source File
  # Begin Source File
  
  SOURCE=.\jk_nt_service.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_pool.c
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_util.c
  # End Source File
  # End Group
  # Begin Group "Header Files"
  
  # PROP Default_Filter "h;hpp;hxx;hm;inl"
  # Begin Source File
  
  SOURCE=..\common\jk_ajp12_worker.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_connect.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_global.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_logger.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_map.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_pool.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_service.h
  # End Source File
  # Begin Source File
  
  SOURCE=..\common\jk_util.h
  # End Source File
  # End Group
  # Begin Group "Resource Files"
  
  # PROP Default_Filter "ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe"
  # End Group
  # End Target
  # End Project