mod_isapi.c revision 1551393ba920a6c7ff283dd2b1d24e4651b7fc05
842ae4bd224140319ae7feec1872b93dfd491143fielding/* ====================================================================
842ae4bd224140319ae7feec1872b93dfd491143fielding * The Apache Software License, Version 1.1
842ae4bd224140319ae7feec1872b93dfd491143fielding *
842ae4bd224140319ae7feec1872b93dfd491143fielding * Copyright (c) 2000 The Apache Software Foundation. All rights
842ae4bd224140319ae7feec1872b93dfd491143fielding * reserved.
842ae4bd224140319ae7feec1872b93dfd491143fielding *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Redistribution and use in source and binary forms, with or without
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * modification, are permitted provided that the following conditions
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * are met:
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 1. Redistributions of source code must retain the above copyright
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * notice, this list of conditions and the following disclaimer.
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd *
ce9621257ef9e54c1bbe5ad8a5f445a1f211c2dcnd * 2. Redistributions in binary form must reproduce the above copyright
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * notice, this list of conditions and the following disclaimer in
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * the documentation and/or other materials provided with the
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * distribution.
36a72c96fc2dda27eadbae8a108fa428cc1419c1wrowe *
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm * 3. The end-user documentation included with the redistribution,
59b96ad34c087942eea06884c97d12c2796a977amturk * if any, must include the following acknowledgment:
c0a549c3f6e8edc87e921cf76fac95d04feba72bwrowe * "This product includes software developed by the
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * Apache Software Foundation (http://www.apache.org/)."
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * Alternately, this acknowledgment may appear in the software itself,
70535d6421eb979ac79d8f49d31cd94d75dd8b2fjorton * if and wherever such third-party acknowledgments normally appear.
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe *
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * 4. The names "Apache" and "Apache Software Foundation" must
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * not be used to endorse or promote products derived from this
79d97c2c5e2d3f8bb2a92cd21b3b4900d7bf04d6mturk * software without prior written permission. For written
79d97c2c5e2d3f8bb2a92cd21b3b4900d7bf04d6mturk * permission, please contact apache@apache.org.
79d97c2c5e2d3f8bb2a92cd21b3b4900d7bf04d6mturk *
79d97c2c5e2d3f8bb2a92cd21b3b4900d7bf04d6mturk * 5. Products derived from this software may not be called "Apache",
2555a6b5da21d61804f47084d8fcc98eb4acbc42wrowe * nor may "Apache" appear in their name, without prior written
1723d9ccdd3b647f5b7bae44cab9ab3eca7a4874dougm * permission of the Apache Software Foundation.
e9501b71b8a1e76384cb010b1e41e76a1e47aacctrawick *
e9501b71b8a1e76384cb010b1e41e76a1e47aacctrawick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
e9501b71b8a1e76384cb010b1e41e76a1e47aacctrawick * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
6335eb31f0f0ed54628a04ed32946360b8b77684minfrin * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * SUCH DAMAGE.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * ====================================================================
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * This software consists of voluntary contributions made by many
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * individuals on behalf of the Apache Software Foundation. For more
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * information on the Apache Software Foundation, please see
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * <http://www.apache.org/>.
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Portions of this software are based upon public domain software
eee895b02dd7867622afd0a8a94f2efc7de9c618wrowe * originally written at the National Center for Supercomputing Applications,
eee895b02dd7867622afd0a8a94f2efc7de9c618wrowe * University of Illinois, Urbana-Champaign.
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe/*
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * mod_isapi.c - Internet Server Application (ISA) module for Apache
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * by Alexei Kosut <akosut@apache.org>
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem *
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem * This module implements Microsoft's ISAPI, allowing Apache (when running
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * under Windows) to load Internet Server Applications (ISAPI extensions).
9f1a88897168c3f1e5009acb585daf01e38a0299jim * It implements all of the ISAPI 2.0 specification, except for the
9f1a88897168c3f1e5009acb585daf01e38a0299jim * "Microsoft-only" extensions dealing with asynchronous I/O. All ISAPI
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk * extensions that use only synchronous I/O and are compatible with the
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim * ISAPI 2.0 specification should work (most ISAPI 1.0 extensions should
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim * function as well).
7af19efc4667363f74d332a8d010b49e88d56fd5trawick *
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * To load, simply place the ISA in a location in the document tree.
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe * Then add an "AddHandler isapi-isa dll" into your config file.
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk * You should now be able to load ISAPI DLLs just be reffering to their
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk * URLs. Make sure the ExecCGI option is active in the directory
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk * the ISA is in.
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
f251b576aa9caeb8876ce9f78fb10bf65eddc97emturk#include "ap_config.h"
f251b576aa9caeb8876ce9f78fb10bf65eddc97emturk#include "httpd.h"
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim#include "http_config.h"
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim#include "http_core.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "http_protocol.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "http_request.h"
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk#include "http_log.h"
0c888b8088644f3a39dcf1998e0304c289532057jim#include "util_script.h"
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk#include "apr_portable.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include "apr_strings.h"
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim/* We use the exact same header file as the original */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#include <HttpExt.h>
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk/* TODO: Unknown errors that must be researched for correct codes */
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#define TODO_ERROR 1
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe/* Seems IIS does not enforce the requirement for \r\n termination on HSE_REQ_SEND_RESPONSE_HEADER,
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim define this to conform */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe#define RELAX_HEADER_RULE
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturkmodule isapi_module;
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe/* Declare the ISAPI functions */
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wroweBOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName,
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer);
38fd849bd99e2765ee633b6dc576b5f17acdc455wroweBOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes,
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe DWORD dwReserved);
38fd849bd99e2765ee633b6dc576b5f17acdc455wroweBOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize);
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturkBOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest,
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk LPVOID lpvBuffer, LPDWORD lpdwSize,
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk LPDWORD lpdwDataType);
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe/*
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe The optimiser blows it totally here. What happens is that autos are addressed relative to the
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim stack pointer, which, of course, moves around. The optimiser seems to lose track of it somewhere
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe between setting HttpExtensionProc's address and calling through it. We work around the problem by
9621e4c4056383e4a2b844b14687bae500b33a82wrowe forcing it to use frame pointers.
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk The revisions below may eliminate this artifact.
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk*/
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk#pragma optimize("y",off)
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem/* Our loaded isapi module description structure */
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem
61d82a1991928d3fa5ee50dc57f2ae3f4b5c781ajimtypedef struct {
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim HINSTANCE handle;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim HSE_VERSION_INFO *pVer;
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe PFN_GETEXTENSIONVERSION GetExtensionVersion;
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe PFN_HTTPEXTENSIONPROC HttpExtensionProc;
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk PFN_TERMINATEEXTENSION TerminateExtension;
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk int refcount;
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk DWORD timeout;
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe BOOL fakeasync;
4c67ef499845a08771e81254ce6eb2324a160bc7wrowe DWORD reportversion;
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe} isapi_loaded;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim/* Our "Connection ID" structure */
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowetypedef struct {
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe LPEXTENSION_CONTROL_BLOCK ecb;
5eb56df4054a0bca4d740eedd7ef277355a2c0adjim isapi_loaded *isa;
5eb56df4054a0bca4d740eedd7ef277355a2c0adjim request_rec *r;
5eb56df4054a0bca4d740eedd7ef277355a2c0adjim PFN_HSE_IO_COMPLETION completion;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim PVOID completion_arg;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim HANDLE complete;
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe ap_status_t retval;
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe} isapi_cid;
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wroweap_status_t isapi_handler (request_rec *r)
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe{
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe ap_table_t *e = r->subprocess_env;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim isapi_loaded *isa;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim isapi_cid *cid;
1dac466bcc84f8ebf410016dcf2a4cd4312e8611wrowe
41c38e78e8e5dc73544571cc2b749d40869e84fawrowe /* Use similar restrictions as CGIs
41c38e78e8e5dc73544571cc2b749d40869e84fawrowe *
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim * If this fails, it's pointless to load the isapi dll.
41c38e78e8e5dc73544571cc2b749d40869e84fawrowe */
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim if (!(ap_allow_options(r) & OPT_EXECCGI))
41c38e78e8e5dc73544571cc2b749d40869e84fawrowe return HTTP_FORBIDDEN;
41c38e78e8e5dc73544571cc2b749d40869e84fawrowe
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim if (r->finfo.protection == 0)
e8f95a682820a599fe41b22977010636be5c2717jim return HTTP_NOT_FOUND;
b842b65e0618c5535233b197f03dc917d184adb3jim
b842b65e0618c5535233b197f03dc917d184adb3jim if (r->finfo.filetype == APR_DIR)
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim return HTTP_FORBIDDEN;
b842b65e0618c5535233b197f03dc917d184adb3jim
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim /* Load the module
b842b65e0618c5535233b197f03dc917d184adb3jim *
b842b65e0618c5535233b197f03dc917d184adb3jim * TODO: Critical section
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim *
b842b65e0618c5535233b197f03dc917d184adb3jim * Warning: cid should not be allocated from pool if we
eee895b02dd7867622afd0a8a94f2efc7de9c618wrowe * cache the isapi process in-memory.
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk *
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk * This code could use cacheing... everything that follows
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim * should only be performed on the first isapi dll invocation,
1d2ff7570139286b0f0d16f92187a16ed5932291mturk * not with every HttpExtensionProc()
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim */
eee895b02dd7867622afd0a8a94f2efc7de9c618wrowe isa = ap_pcalloc(r->pool, sizeof(isapi_module));
eee895b02dd7867622afd0a8a94f2efc7de9c618wrowe isa->pVer = ap_pcalloc(r->pool, sizeof(HSE_VERSION_INFO));
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk isa->refcount = 0;
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim /* TODO: These may need to become overrideable, so that we
1d2ff7570139286b0f0d16f92187a16ed5932291mturk * assure a given isapi can be fooled into behaving well.
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim */
eee895b02dd7867622afd0a8a94f2efc7de9c618wrowe isa->timeout = INFINITE; /* microsecs */
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk isa->fakeasync = TRUE;
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk isa->reportversion = MAKELONG(0, 5); /* Revision 5.0 */
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk
4e0b7720fce1e872ea6afd2421b8b6addacf9bd0jim if (!(isa->handle = LoadLibraryEx(r->filename, NULL,
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk LOAD_WITH_ALTERED_SEARCH_PATH))) {
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk "ISAPI %s failed to load", r->filename);
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk return HTTP_INTERNAL_SERVER_ERROR;
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk }
e8f95a682820a599fe41b22977010636be5c2717jim
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk if (!(isa->GetExtensionVersion =
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk (void *)(GetProcAddress(isa->handle, "GetExtensionVersion")))) {
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
e8f95a682820a599fe41b22977010636be5c2717jim "ISAPI %s is missing GetExtensionVersion()",
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk r->filename);
e2b702094817c78498e6de567b9548ef794c33d3jim FreeLibrary(isa->handle);
4e0b7720fce1e872ea6afd2421b8b6addacf9bd0jim return HTTP_INTERNAL_SERVER_ERROR;
7ce17736e4802a923eed275812647a7c3e9ad76ejim }
f73a8fabbdc4ec11c8b475e9f48539de0c4f82ebmturk
e8f95a682820a599fe41b22977010636be5c2717jim if (!(isa->HttpExtensionProc =
07ac837c886b356dc96e83cf82fb348eb56406d9jim (void *)(GetProcAddress(isa->handle, "HttpExtensionProc")))) {
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim "ISAPI %s is missing HttpExtensionProc()",
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim r->filename);
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim FreeLibrary(isa->handle);
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim return HTTP_INTERNAL_SERVER_ERROR;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim }
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim
07ac837c886b356dc96e83cf82fb348eb56406d9jim /* TerminateExtension() is an optional interface */
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim
07ac837c886b356dc96e83cf82fb348eb56406d9jim isa->TerminateExtension = (void *)(GetProcAddress(isa->handle, "TerminateExtension"));
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim /* Run GetExtensionVersion() */
07ac837c886b356dc96e83cf82fb348eb56406d9jim
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim if (!(*isa->GetExtensionVersion)(isa->pVer)) {
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim /* ### euh... we're passing the wrong type of error code here */
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim ap_log_rerror(APLOG_MARK, APLOG_ALERT, HTTP_INTERNAL_SERVER_ERROR, r,
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim "ISAPI %s call GetExtensionVersion() failed",
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim r->filename);
5d392744e2077f71f34ce098ab49d2c0ddcf4ea3jim FreeLibrary(isa->handle);
188befd3a49e3a126bd801d7dc5a7f6e63ad4332mturk return HTTP_INTERNAL_SERVER_ERROR;
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem }
188befd3a49e3a126bd801d7dc5a7f6e63ad4332mturk
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem /* Load of this module completed, this is the point at which *isa
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem * could be cached for later invocation.
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem *
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem * on to invoking this request...
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim */
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim
188befd3a49e3a126bd801d7dc5a7f6e63ad4332mturk /* Set up variables */
f185ce14f5dd540ae54659f764989c017c619485jim ap_add_common_vars(r);
f185ce14f5dd540ae54659f764989c017c619485jim ap_add_cgi_vars(r);
f185ce14f5dd540ae54659f764989c017c619485jim
f185ce14f5dd540ae54659f764989c017c619485jim /* Set up connection structure and ecb */
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim cid = ap_pcalloc(r->pool, sizeof(isapi_cid));
f185ce14f5dd540ae54659f764989c017c619485jim cid->ecb = ap_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK));
f921cd430a2ea23fcaedfdfc7439163f63c8472arpluem cid->ecb->ConnID = (HCONN)cid;
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem /* TODO: Critical section */
f921cd430a2ea23fcaedfdfc7439163f63c8472arpluem ++isa->refcount;
f921cd430a2ea23fcaedfdfc7439163f63c8472arpluem cid->isa = isa;
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem cid->r = r;
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem cid->r->status = 0;
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem cid->complete = NULL;
90f18725dbb9bdfba94da22aa60f94dfb759a8ferpluem cid->completion = NULL;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim cid->retval = APR_SUCCESS;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim
f921cd430a2ea23fcaedfdfc7439163f63c8472arpluem cid->ecb->cbSize = sizeof(EXTENSION_CONTROL_BLOCK);
bf3f3b52289ee37f40842fc836ff92dd202742afpquerna cid->ecb->dwVersion = isa->reportversion;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim cid->ecb->dwHttpStatusCode = 0;
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim strcpy(cid->ecb->lpszLogData, "");
2f1146e06a1bfa371573a3f3fb0379448e18aaedjim // TODO: are copies really needed here?
bf3f3b52289ee37f40842fc836ff92dd202742afpquerna cid->ecb->lpszMethod = ap_pstrdup(r->pool, (char*) r->method);
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->ecb->lpszQueryString = ap_pstrdup(r->pool,
65efbf0826de766a90d745cc44427bfa4e2447b6mturk (char*) ap_table_get(e, "QUERY_STRING"));
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->ecb->lpszPathInfo = ap_pstrdup(r->pool,
4415d997ac73262e513c0a571bd5be4f609040bawrowe (char*) ap_table_get(e, "PATH_INFO"));
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->ecb->lpszPathTranslated = ap_pstrdup(r->pool,
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe (char*) ap_table_get(e, "PATH_TRANSLATED"));
1febae173a82bc2a71c3c0ba4105cf674000791bjim cid->ecb->lpszContentType = ap_pstrdup(r->pool,
1febae173a82bc2a71c3c0ba4105cf674000791bjim (char*) ap_table_get(e, "CONTENT_TYPE"));
eee895b02dd7867622afd0a8a94f2efc7de9c618wrowe /* Set up the callbacks */
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->ecb->GetServerVariable = &GetServerVariable;
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->ecb->WriteClient = &WriteClient;
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->ecb->ReadClient = &ReadClient;
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->ecb->ServerSupportFunction = &ServerSupportFunction;
4415d997ac73262e513c0a571bd5be4f609040bawrowe
4415d997ac73262e513c0a571bd5be4f609040bawrowe
c3dc78855363fa6e8ecfc2bb8e2927efcd31d31djfclere /* Set up client input */
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk cid->retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk if (cid->retval) {
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk if (isa->TerminateExtension) {
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim }
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim FreeLibrary(isa->handle);
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim return cid->retval;
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim }
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim
d20993e12a1caa8952c6d964ed0fbb92b7f97d79jim if (ap_should_client_block(r)) {
c3dc78855363fa6e8ecfc2bb8e2927efcd31d31djfclere /* Unlike IIS, which limits this to 48k, we read the whole
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim * sucker in. I suppose this could be bad for memory if someone
c3dc78855363fa6e8ecfc2bb8e2927efcd31d31djfclere * uploaded the complete works of Shakespeare. Well, WebSite
4415d997ac73262e513c0a571bd5be4f609040bawrowe * does the same thing.
4415d997ac73262e513c0a571bd5be4f609040bawrowe *
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk * But we can be smarter and read up to our 48k and then allow
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk * the ISAPI app to read further blocks as desired.
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk */
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk long to_read = atol(ap_table_get(e, "CONTENT_LENGTH"));
4415d997ac73262e513c0a571bd5be4f609040bawrowe long read;
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim
4415d997ac73262e513c0a571bd5be4f609040bawrowe /* Actually, let's cap it at 48k, until we figure out what
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim * to do with this... we don't want a Content-Length: 1000000000
4415d997ac73262e513c0a571bd5be4f609040bawrowe * taking out the machine.
4415d997ac73262e513c0a571bd5be4f609040bawrowe */
4415d997ac73262e513c0a571bd5be4f609040bawrowe
4415d997ac73262e513c0a571bd5be4f609040bawrowe if (to_read > 49152) {
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk if (isa->TerminateExtension)
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk FreeLibrary(isa->handle);
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk return HTTP_REQUEST_ENTITY_TOO_LARGE;
01261c7d9578aadd1891f94c8ee03f32ba51db3dmturk }
4415d997ac73262e513c0a571bd5be4f609040bawrowe
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->ecb->lpbData = ap_pcalloc(r->pool, 1 + to_read);
eee895b02dd7867622afd0a8a94f2efc7de9c618wrowe
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim if ((read = ap_get_client_block(r, cid->ecb->lpbData, to_read)) < 0) {
4415d997ac73262e513c0a571bd5be4f609040bawrowe if (isa->TerminateExtension)
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk FreeLibrary(isa->handle);
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk return HTTP_INTERNAL_SERVER_ERROR;
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk }
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk /* Although its not to spec, IIS seems to null-terminate
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk * its lpdData string. So we will too. To make sure
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim * cbAvailable matches cbTotalBytes, we'll up the latter
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim * and equalize them.
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk */
9e3209bc06ddf32f23e4b254faa45914bc323cc9jim cid->ecb->cbAvailable = cid->ecb->cbTotalBytes = read + 1;
c332befc1519a1016d8de07608f0b859e6fab580jim cid->ecb->lpbData[read] = '\0';
5b439d3976ab9363288cf5132902fad230777523jim }
5b439d3976ab9363288cf5132902fad230777523jim else {
361051c5d96d51ff2f707777b8f629a56799ef02jorton cid->ecb->cbTotalBytes = 0;
361051c5d96d51ff2f707777b8f629a56799ef02jorton cid->ecb->cbAvailable = 0;
5b439d3976ab9363288cf5132902fad230777523jim cid->ecb->lpbData = NULL;
5b439d3976ab9363288cf5132902fad230777523jim }
c332befc1519a1016d8de07608f0b859e6fab580jim
1febae173a82bc2a71c3c0ba4105cf674000791bjim /* All right... try and run the sucker */
1febae173a82bc2a71c3c0ba4105cf674000791bjim cid->retval = (*isa->HttpExtensionProc)(cid->ecb);
9e3209bc06ddf32f23e4b254faa45914bc323cc9jim
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim /* Set the status (for logging) */
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim if (cid->ecb->dwHttpStatusCode) {
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim cid->r->status = cid->ecb->dwHttpStatusCode;
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim }
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim /* Check for a log message - and log it */
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim if (cid->ecb->lpszLogData && *cid->ecb->lpszLogData)
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim "ISAPI %s: %s", r->filename, cid->ecb->lpszLogData);
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim switch(cid->retval) {
ff4ec92f5bb8d43b3ba1979ccda94f07961bf323jim case HSE_STATUS_SUCCESS:
b92a868b537899a51efd8c200c396fa51c63839dtrawick case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
9f22e9ea026e74271ddced44f6d54fa846ddc9bcwrowe /* Ignore the keepalive stuff; Apache handles it just fine without
d46dfdce9351f52a971777948d9b02f8fc668ff8niq * the ISA's "advice".
d46dfdce9351f52a971777948d9b02f8fc668ff8niq * Per Microsoft: "In IIS versions 4.0 and later, the return
d46dfdce9351f52a971777948d9b02f8fc668ff8niq * values HSE_STATUS_SUCCESS and HSE_STATUS_SUCCESS_AND_KEEP_CONN
9f22e9ea026e74271ddced44f6d54fa846ddc9bcwrowe * are functionally identical: Keep-Alive connections are
9f22e9ea026e74271ddced44f6d54fa846ddc9bcwrowe * maintained, if supported by the client."
d46dfdce9351f52a971777948d9b02f8fc668ff8niq * ... so we were pat all this time
d46dfdce9351f52a971777948d9b02f8fc668ff8niq */
9f22e9ea026e74271ddced44f6d54fa846ddc9bcwrowe break;
d46dfdce9351f52a971777948d9b02f8fc668ff8niq
d46dfdce9351f52a971777948d9b02f8fc668ff8niq case HSE_STATUS_PENDING:
d46dfdce9351f52a971777948d9b02f8fc668ff8niq /* emulating async behavior...
3a49a6c98ef80c71830e66e7f8f46083001b494ctrawick *
d46dfdce9351f52a971777948d9b02f8fc668ff8niq * Create a cid->completed event and wait on it for some timeout
d46dfdce9351f52a971777948d9b02f8fc668ff8niq * so that the app thinks is it running async.
b92a868b537899a51efd8c200c396fa51c63839dtrawick *
d46dfdce9351f52a971777948d9b02f8fc668ff8niq * All async ServerSupportFunction calls will be handled through
d46dfdce9351f52a971777948d9b02f8fc668ff8niq * the registered IO_COMPLETION hook.
d46dfdce9351f52a971777948d9b02f8fc668ff8niq */
d46dfdce9351f52a971777948d9b02f8fc668ff8niq
d46dfdce9351f52a971777948d9b02f8fc668ff8niq if (!isa->fakeasync) {
a652b68dea502131f70084ead7981d5fc754cd34jim ap_log_rerror(APLOG_MARK, APLOG_WARNING, APR_ENOTIMPL, r,
a652b68dea502131f70084ead7981d5fc754cd34jim "ISAPI %s asynch I/O request refused",
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim r->filename);
5bfaaf573bacb45c1cf290ce85ecc676587e8a64jim cid->retval = APR_ENOTIMPL;
a652b68dea502131f70084ead7981d5fc754cd34jim }
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim else {
a652b68dea502131f70084ead7981d5fc754cd34jim cid->complete = CreateEvent(NULL, FALSE, FALSE, NULL);
a652b68dea502131f70084ead7981d5fc754cd34jim if (WaitForSingleObject(cid->complete, isa->timeout)
a652b68dea502131f70084ead7981d5fc754cd34jim == WAIT_TIMEOUT) {
cb7cf74a315df272e2ec329ce2ef1d50b82b8384jim /* TODO: Now what... if this hung, then do we kill our own
a652b68dea502131f70084ead7981d5fc754cd34jim * thread to force it's death? For now leave timeout = -1
a652b68dea502131f70084ead7981d5fc754cd34jim */
a652b68dea502131f70084ead7981d5fc754cd34jim }
a652b68dea502131f70084ead7981d5fc754cd34jim }
a652b68dea502131f70084ead7981d5fc754cd34jim break;
a652b68dea502131f70084ead7981d5fc754cd34jim
a652b68dea502131f70084ead7981d5fc754cd34jim case HSE_STATUS_ERROR:
a652b68dea502131f70084ead7981d5fc754cd34jim /* end response if we have yet to do so.
a652b68dea502131f70084ead7981d5fc754cd34jim */
4415d997ac73262e513c0a571bd5be4f609040bawrowe cid->retval = HTTP_INTERNAL_SERVER_ERROR;
65efbf0826de766a90d745cc44427bfa4e2447b6mturk break;
4415d997ac73262e513c0a571bd5be4f609040bawrowe
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe default:
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe /* TODO: log unrecognized retval for debugging
38fd849bd99e2765ee633b6dc576b5f17acdc455wrowe */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding cid->retval = HTTP_INTERNAL_SERVER_ERROR;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding break;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
00211b036b78699ace57a6d800a52e6c2d57652fnd /* All done with the DLL... get rid of it...
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *
00211b036b78699ace57a6d800a52e6c2d57652fnd * If optionally cached, pass HSE_TERM_ADVISORY_UNLOAD,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * and if it returns TRUE, unload, otherwise, cache it.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if (isa->TerminateExtension) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard FreeLibrary(isa->handle);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* TODO: Crit section */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard cid->isa = NULL;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard --isa->refcount;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard isa->handle = NULL;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return cid->retval;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard#pragma optimize("",on)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardBOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding{
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding request_rec *r = ((isapi_cid *)hConn)->r;
00211b036b78699ace57a6d800a52e6c2d57652fnd ap_table_t *e = r->subprocess_env;
00211b036b78699ace57a6d800a52e6c2d57652fnd const char *result;
00211b036b78699ace57a6d800a52e6c2d57652fnd
00211b036b78699ace57a6d800a52e6c2d57652fnd /* Mostly, we just grab it from the environment, but there are
00211b036b78699ace57a6d800a52e6c2d57652fnd * a couple of special cases
00211b036b78699ace57a6d800a52e6c2d57652fnd */
00211b036b78699ace57a6d800a52e6c2d57652fnd
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!strcasecmp(lpszVariableName, "UNMAPPED_REMOTE_USER")) {
50b2d068ddf98cf75622a0020cd143d379d1b235jfclere /* We don't support NT users, so this is always the same as
50b2d068ddf98cf75622a0020cd143d379d1b235jfclere * REMOTE_USER
50b2d068ddf98cf75622a0020cd143d379d1b235jfclere */
35630e8756729a29273ef1a5c879b90df3594d66rjung result = ap_table_get(e, "REMOTE_USER");
50b2d068ddf98cf75622a0020cd143d379d1b235jfclere }
50b2d068ddf98cf75622a0020cd143d379d1b235jfclere else if (!strcasecmp(lpszVariableName, "SERVER_PORT_SECURE")) {
50b2d068ddf98cf75622a0020cd143d379d1b235jfclere /* Apache doesn't support secure requests inherently, so
00211b036b78699ace57a6d800a52e6c2d57652fnd * we have no way of knowing. We'll be conservative, and say
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * all requests are insecure.
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding result = "0";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding else if (!strcasecmp(lpszVariableName, "URL")) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding result = r->uri;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding else {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding result = ap_table_get(e, lpszVariableName);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (result) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (strlen(result) > *lpdwSizeofBuffer) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *lpdwSizeofBuffer = strlen(result);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding SetLastError(ERROR_INSUFFICIENT_BUFFER);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return FALSE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding strncpy(lpvBuffer, result, *lpdwSizeofBuffer);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return TRUE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Didn't find it */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding SetLastError(ERROR_INVALID_INDEX);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return FALSE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding}
33cb45dc8c5106018b7c2f6ae42478b109423e0eniq
a812b025d139f465a31c76fc02ed162ed5271b03ndBOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding DWORD dwReserved)
16d38ac65d7e54cd44eeda7b23f84ee68b35094ewrowe{
16d38ac65d7e54cd44eeda7b23f84ee68b35094ewrowe request_rec *r = ((isapi_cid *)ConnID)->r;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding int writ; /* written, actually, but why shouldn't I make up words? */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* We only support synchronous writing */
7b6ba9c468f26bdb3492d5e8cb79628a3b04e8c8wrowe if (dwReserved && dwReserved != HSE_IO_SYNC) {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_log_rerror(APLOG_MARK, APLOG_WARNING, ERROR_INVALID_PARAMETER, r,
e8f95a682820a599fe41b22977010636be5c2717jim "ISAPI %s asynch write", r->filename);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard SetLastError(ERROR_INVALID_PARAMETER);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return FALSE;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard if ((writ = ap_rwrite(Buffer, *lpwdwBytes, r)) == EOF) {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding SetLastError(WSAEDISCON); /* TODO: Find the right error code */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return FALSE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard *lpwdwBytes = writ;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return TRUE;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardBOOL WINAPI ReadClient (HCONN ConnID, LPVOID lpvBuffer, LPDWORD lpdwSize)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard{
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* TODO: If the request was a huge transmit or chunked, continue piping the
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * request here, but if it's of a sane size, continue to ...
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return TRUE;
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq}
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
e99dfd55d29a7b4209b814efc7270d0b74ccee74niqstatic char* ComposeHeaders(request_rec *r, char* data)
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq{
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq /* We *should* break before this while loop ends */
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq while (*data)
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq {
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq char *value, *lf = strchr(data, '\n');
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq int p;
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq#ifdef RELAX_HEADER_RULE
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq if (lf)
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq *lf = '\0';
188befd3a49e3a126bd801d7dc5a7f6e63ad4332mturk#else
9df9016759ec9327e256d7fff1af56ddfadb721cniq if (!lf) { /* Huh? Invalid data, I think */
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq ap_log_rerror(APLOG_MARK, APLOG_ERR, r,
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq "ISAPI %s sent invalid headers", r->filename);
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq SetLastError(TODO_ERROR);
9df9016759ec9327e256d7fff1af56ddfadb721cniq return FALSE;
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq }
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq /* Get rid of \n and \r */
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq *lf = '\0';
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq#endif
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq p = strlen(data);
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq if (p > 0 && data[p-1] == '\r') data[p-1] = '\0';
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq /* End of headers */
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq if (*data == '\0') {
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq#ifdef RELAX_HEADER_RULE
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq if (lf)
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq#endif
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq data = lf + 1; /* Reset data */
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq break;
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq }
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq if (!(value = strchr(data, ':'))) {
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq SetLastError(TODO_ERROR);
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq /* ### euh... we're passing the wrong type of error
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq ### code here */
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq ap_log_rerror(APLOG_MARK, APLOG_ERR, HTTP_INTERNAL_SERVER_ERROR, r,
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq "ISAPI %s sent invalid headers", r->filename);
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq return FALSE;
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq }
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq *value++ = '\0';
997023faa943892aae20d092044aa983c2936982niq while (*value && ap_isspace(*value)) ++value;
997023faa943892aae20d092044aa983c2936982niq
997023faa943892aae20d092044aa983c2936982niq /* Check all the special-case headers. Similar to what
997023faa943892aae20d092044aa983c2936982niq * ap_scan_script_header_err() does (see that function for
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * more detail)
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq */
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
df419be6d7d4b68823efa05722375552af49c2b6minfrin if (!strcasecmp(data, "Content-Type"))
e8ecc839fc57f2157ff10eba188d7aa3c0244174jim {
e8ecc839fc57f2157ff10eba188d7aa3c0244174jim /* Nuke trailing whitespace */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding char *tmp;
df419be6d7d4b68823efa05722375552af49c2b6minfrin char *endp = value + strlen(value) - 1;
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq while (endp > value && ap_isspace(*endp))
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq *endp-- = '\0';
dcda744296f197717c5105fd197e94ceba7880d7jim
28fe44817329b1183f64e878c258962f90423a8dniq tmp = ap_pstrdup (r->pool, value);
dcda744296f197717c5105fd197e94ceba7880d7jim ap_str_tolower(tmp);
28fe44817329b1183f64e878c258962f90423a8dniq r->content_type = tmp;
df419be6d7d4b68823efa05722375552af49c2b6minfrin }
df419be6d7d4b68823efa05722375552af49c2b6minfrin else if (!strcasecmp(data, "Content-Length")) {
df419be6d7d4b68823efa05722375552af49c2b6minfrin ap_table_set(r->headers_out, data, value);
e8ecc839fc57f2157ff10eba188d7aa3c0244174jim }
df419be6d7d4b68823efa05722375552af49c2b6minfrin else if (!strcasecmp(data, "Transfer-Encoding")) {
df419be6d7d4b68823efa05722375552af49c2b6minfrin ap_table_set(r->headers_out, data, value);
df419be6d7d4b68823efa05722375552af49c2b6minfrin }
df419be6d7d4b68823efa05722375552af49c2b6minfrin else if (!strcasecmp(data, "Set-Cookie")) {
df419be6d7d4b68823efa05722375552af49c2b6minfrin ap_table_add(r->err_headers_out, data, value);
df419be6d7d4b68823efa05722375552af49c2b6minfrin }
df419be6d7d4b68823efa05722375552af49c2b6minfrin else {
df419be6d7d4b68823efa05722375552af49c2b6minfrin ap_table_merge(r->err_headers_out, data, value);
df419be6d7d4b68823efa05722375552af49c2b6minfrin }
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Reset data */
df419be6d7d4b68823efa05722375552af49c2b6minfrin#ifdef RELAX_HEADER_RULE
df419be6d7d4b68823efa05722375552af49c2b6minfrin if (!lf) {
df419be6d7d4b68823efa05722375552af49c2b6minfrin data += p;
df419be6d7d4b68823efa05722375552af49c2b6minfrin break;
df419be6d7d4b68823efa05722375552af49c2b6minfrin }
df419be6d7d4b68823efa05722375552af49c2b6minfrin#endif
df419be6d7d4b68823efa05722375552af49c2b6minfrin data = lf + 1;
df419be6d7d4b68823efa05722375552af49c2b6minfrin }
df419be6d7d4b68823efa05722375552af49c2b6minfrin return data;
df419be6d7d4b68823efa05722375552af49c2b6minfrin}
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin/* XXX: There is an O(n^2) attack possible here. */
df419be6d7d4b68823efa05722375552af49c2b6minfrinBOOL WINAPI ServerSupportFunction (HCONN hConn, DWORD dwHSERequest,
df419be6d7d4b68823efa05722375552af49c2b6minfrin LPVOID lpvBuffer, LPDWORD lpdwSize,
df419be6d7d4b68823efa05722375552af49c2b6minfrin LPDWORD lpdwDataType)
df419be6d7d4b68823efa05722375552af49c2b6minfrin{
df419be6d7d4b68823efa05722375552af49c2b6minfrin isapi_cid *cid = (isapi_cid *)hConn;
df419be6d7d4b68823efa05722375552af49c2b6minfrin request_rec *r = cid->r;
df419be6d7d4b68823efa05722375552af49c2b6minfrin request_rec *subreq;
df419be6d7d4b68823efa05722375552af49c2b6minfrin char *data;
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin switch (dwHSERequest) {
df419be6d7d4b68823efa05722375552af49c2b6minfrin case HSE_REQ_SEND_URL_REDIRECT_RESP:
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Set the status to be returned when the HttpExtensionProc()
df419be6d7d4b68823efa05722375552af49c2b6minfrin * is done.
df419be6d7d4b68823efa05722375552af49c2b6minfrin */
df419be6d7d4b68823efa05722375552af49c2b6minfrin ap_table_set (r->headers_out, "Location", lpvBuffer);
df419be6d7d4b68823efa05722375552af49c2b6minfrin cid->r->status = cid->ecb->dwHttpStatusCode
df419be6d7d4b68823efa05722375552af49c2b6minfrin = HTTP_MOVED_TEMPORARILY;
df419be6d7d4b68823efa05722375552af49c2b6minfrin return TRUE;
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin case HSE_REQ_SEND_URL:
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Read any additional input */
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin if (r->remaining > 0) {
df419be6d7d4b68823efa05722375552af49c2b6minfrin char argsbuffer[HUGE_STRING_LEN];
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin while (ap_get_client_block(r, argsbuffer, HUGE_STRING_LEN));
df419be6d7d4b68823efa05722375552af49c2b6minfrin }
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Reset the method to GET */
df419be6d7d4b68823efa05722375552af49c2b6minfrin r->method = ap_pstrdup(r->pool, "GET");
df419be6d7d4b68823efa05722375552af49c2b6minfrin r->method_number = M_GET;
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Don't let anyone think there's still data */
df419be6d7d4b68823efa05722375552af49c2b6minfrin ap_table_unset(r->headers_in, "Content-Length");
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin ap_internal_redirect((char *)lpvBuffer, r);
df419be6d7d4b68823efa05722375552af49c2b6minfrin return TRUE;
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin case HSE_REQ_SEND_RESPONSE_HEADER:
df419be6d7d4b68823efa05722375552af49c2b6minfrin r->status_line = lpvBuffer ? lpvBuffer : ap_pstrdup(r->pool, "200 OK");
df419be6d7d4b68823efa05722375552af49c2b6minfrin sscanf(r->status_line, "%d", &r->status);
df419be6d7d4b68823efa05722375552af49c2b6minfrin cid->ecb->dwHttpStatusCode = r->status;
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Now fill in the HTTP headers, and the rest of it. Ick.
df419be6d7d4b68823efa05722375552af49c2b6minfrin * lpdwDataType contains a string that has headers (in MIME
df419be6d7d4b68823efa05722375552af49c2b6minfrin * format), a blank like, then (possibly) data. We need
df419be6d7d4b68823efa05722375552af49c2b6minfrin * to parse it.
df419be6d7d4b68823efa05722375552af49c2b6minfrin *
df419be6d7d4b68823efa05722375552af49c2b6minfrin * Easy case first:
df419be6d7d4b68823efa05722375552af49c2b6minfrin */
df419be6d7d4b68823efa05722375552af49c2b6minfrin if (!lpdwDataType) {
df419be6d7d4b68823efa05722375552af49c2b6minfrin ap_send_http_header(r);
df419be6d7d4b68823efa05722375552af49c2b6minfrin return TRUE;
df419be6d7d4b68823efa05722375552af49c2b6minfrin }
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Make a copy - don't disturb the original */
df419be6d7d4b68823efa05722375552af49c2b6minfrin data = ap_pstrdup(r->pool, (char *)lpdwDataType);
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Parse them out, or die trying */
a812b025d139f465a31c76fc02ed162ed5271b03nd data = ComposeHeaders(r, data);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (!data)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return FALSE;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* All the headers should be set now */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ap_send_http_header(r);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
a812b025d139f465a31c76fc02ed162ed5271b03nd /* Any data left should now be sent directly */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (*data)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ap_rputs(data, r);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return TRUE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
df419be6d7d4b68823efa05722375552af49c2b6minfrin case HSE_REQ_DONE_WITH_SESSION:
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* Signal to resume the thread completing this request
df419be6d7d4b68823efa05722375552af49c2b6minfrin */
df419be6d7d4b68823efa05722375552af49c2b6minfrin if (cid->complete)
e8ecc839fc57f2157ff10eba188d7aa3c0244174jim SetEvent(cid->complete);
df419be6d7d4b68823efa05722375552af49c2b6minfrin return TRUE;
df419be6d7d4b68823efa05722375552af49c2b6minfrin
28fe44817329b1183f64e878c258962f90423a8dniq case HSE_REQ_MAP_URL_TO_PATH:
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* Map a URL to a filename */
28fe44817329b1183f64e878c258962f90423a8dniq subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, (char *)lpvBuffer,
df419be6d7d4b68823efa05722375552af49c2b6minfrin *lpdwSize), r);
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin GetFullPathName(subreq->filename, *lpdwSize - 1, (char *)lpvBuffer, NULL);
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin /* IIS puts a trailing slash on directories, Apache doesn't */
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin if (subreq->finfo.filetype == APR_DIR) {
e8ecc839fc57f2157ff10eba188d7aa3c0244174jim int l = strlen((char *)lpvBuffer);
df419be6d7d4b68823efa05722375552af49c2b6minfrin
df419be6d7d4b68823efa05722375552af49c2b6minfrin ((char *)lpvBuffer)[l] = '\\';
28fe44817329b1183f64e878c258962f90423a8dniq ((char *)lpvBuffer)[l + 1] = '\0';
dcda744296f197717c5105fd197e94ceba7880d7jim }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return TRUE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding case HSE_REQ_GET_SSPI_INFO:
9b3001f2097437c3c605d29e353fda5131b9952bminfrin SetLastError(ERROR_INVALID_PARAMETER);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return FALSE;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe case HSE_APPEND_LOG_PARAMETER:
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* Log lpvBuffer, of lpdwSize bytes, in the URI Query (cs-uri-query) field
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * This code will do for now...
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_log_rerror(APLOG_MARK, APLOG_INFO, 0, r,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe "ISAPI %s: %s", cid->r->filename,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard (char*) lpvBuffer);
e8f95a682820a599fe41b22977010636be5c2717jim return TRUE;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe case HSE_REQ_IO_COMPLETION:
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* TODO: Emulate a completion port, if we can...
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * Record the callback address and user defined argument...
e8f95a682820a599fe41b22977010636be5c2717jim * we will call this after any async request (e.g. transmitfile)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * as if the request had completed async execution.
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * Per MS docs... HSE_REQ_IO_COMPLETION replaces any prior call
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe * to HSE_REQ_IO_COMPLETION, and lpvBuffer may be set to NULL.
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe if (!cid->isa->fakeasync)
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return FALSE;
e8f95a682820a599fe41b22977010636be5c2717jim cid->completion = (PFN_HSE_IO_COMPLETION) lpvBuffer;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe cid->completion_arg = (PVOID) lpdwDataType;
e8f95a682820a599fe41b22977010636be5c2717jim return TRUE;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe case HSE_REQ_TRANSMIT_FILE:
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* Use TransmitFile... nothing wrong with that :)
e8f95a682820a599fe41b22977010636be5c2717jim */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* ### euh... we're passing the wrong type of error code here */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe ap_log_rerror(APLOG_MARK, APLOG_WARNING,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe HTTP_INTERNAL_SERVER_ERROR, r,
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe "ISAPI asynchronous I/O not supported: %s",
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe r->filename);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return FALSE;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe case HSE_REQ_REFRESH_ISAPI_ACL:
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe SetLastError(ERROR_INVALID_PARAMETER);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return FALSE;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe case HSE_REQ_IS_KEEP_CONN:
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe SetLastError(ERROR_INVALID_PARAMETER);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return FALSE;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
8632261c895a84c88ae6ade6ea4c62b27bd22b3ebrianp case HSE_REQ_ASYNC_READ_CLIENT:
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe SetLastError(ERROR_INVALID_PARAMETER);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return FALSE;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe case HSE_REQ_GET_IMPERSONATION_TOKEN: /* Added in ISAPI 4.0 */
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe SetLastError(ERROR_INVALID_PARAMETER);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return FALSE;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe case HSE_REQ_MAP_URL_TO_PATH_EX:
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe SetLastError(ERROR_INVALID_PARAMETER);
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe return FALSE;
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe /* TODO: Not quite ready for prime time yet */
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Map a URL to a filename */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding subreq = ap_sub_req_lookup_uri(ap_pstrndup(r->pool, (char *)lpvBuffer,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *lpdwSize), r);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding GetFullPathName(subreq->filename, *lpdwSize - 1, (char *)lpvBuffer, NULL);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* IIS puts a trailing slash on directories, Apache doesn't */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (subreq->finfo.filetype == APR_DIR) {
68ce856106f153813339db8670f6cd0ab8dea484minfrin int l = strlen((char *)lpvBuffer);
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq ((char *)lpvBuffer)[l] = '\\';
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ((char *)lpvBuffer)[l + 1] = '\0';
45dac0729754e413ff7c673481b219e9ab1a11f1bnicholes }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding lpdwDataType = (LPDWORD) ap_palloc(r->pool, sizeof(HSE_URL_MAPEX_INFO));
2ceedfca3a2fdfdb5ff60ca17f030ce91f6331cbwrowe strncpy(((LPHSE_URL_MAPEX_INFO)lpdwDataType)->lpszPath,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding (char *) lpvBuffer, MAX_PATH);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ((LPHSE_URL_MAPEX_INFO)lpdwDataType)->dwFlags = 0;
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq /* is a combination of:
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_READ Allow for read.
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_WRITE Allow for write.
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_EXECUTE Allow for execute.
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_SSL Require SSL.
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_DONT_CACHE Don't cache (virtual root only).
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_NEGO_CERT Allow client SSL certifications.
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_REQUIRE_CERT Require client SSL certifications.
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_MAP_CERT Map SSL certification to a Windows account.
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_SSL128 Requires a 128-bit SSL.
e99dfd55d29a7b4209b814efc7270d0b74ccee74niq * HSE_URL_FLAGS_SCRIPT Allows for script execution.
68ce856106f153813339db8670f6cd0ab8dea484minfrin */
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin /* (LPHSE_URL_MAPEX_INFO)lpdwDataType)->cchMatchingPath
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * (LPHSE_URL_MAPEX_INFO)lpdwDataType)->cchMatchingURL
68ce856106f153813339db8670f6cd0ab8dea484minfrin */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return TRUE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard case HSE_REQ_ABORTIVE_CLOSE:
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding SetLastError(ERROR_INVALID_PARAMETER);
65efbf0826de766a90d745cc44427bfa4e2447b6mturk return FALSE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
11c3b5180e1de6776035320b012a28bb146e7b46chuck case HSE_REQ_GET_CERT_INFO_EX: /* Added in ISAPI 4.0 */
11c3b5180e1de6776035320b012a28bb146e7b46chuck SetLastError(ERROR_INVALID_PARAMETER);
11c3b5180e1de6776035320b012a28bb146e7b46chuck return FALSE;
11c3b5180e1de6776035320b012a28bb146e7b46chuck
11c3b5180e1de6776035320b012a28bb146e7b46chuck case HSE_REQ_SEND_RESPONSE_HEADER_EX: /* Added in ISAPI 4.0 */
11c3b5180e1de6776035320b012a28bb146e7b46chuck SetLastError(ERROR_INVALID_PARAMETER);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding return FALSE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* TODO: Not quite ready for prime time */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->pszStatus
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding && ((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->cchStatus) {
d7387fcd4969206172e3a2a8bbcd25a3d7011ac5rbb r->status_line = ap_pstrndup(r->pool,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->pszStatus,
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding ((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->cchStatus);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
d4a7ca64aa12da0c1b44b0281e93973a89cefeedmartin else {
d4a7ca64aa12da0c1b44b0281e93973a89cefeedmartin r->status_line = ap_pstrdup(r->pool, "200 OK");
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
65efbf0826de766a90d745cc44427bfa4e2447b6mturk sscanf(r->status_line, "%d", &r->status);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding cid->ecb->dwHttpStatusCode = r->status;
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding if (((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->pszHeader
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding && ((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->cchHeader)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding {
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm /* Make a copy - don't disturb the original */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard data = ap_pstrndup(r->pool,
b999f6ba2a266bf9a92687f31bb7e76021ac5891ianh ((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->pszHeader,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard ((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->cchHeader);
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* Parse them out, or die trying */
e2de0e939faab767454a164c7d2e8ea710fd1a26sf data = ComposeHeaders(r, data);
1cde33c7e2019830f8fb3224e01649305583916etrawick if (!data)
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard return FALSE;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard else {
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding data = "\0";
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding }
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding /* ((LPHSE_SEND_HEADER_EX_INFO)lpvBuffer)->fKeepConn;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding *
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * Now how are we about to start listening to an ISAPI's
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding * idea of keeping or closing a connection? Seriously :)
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding */
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
a8523e2451f03f4a30030b7bda643a23a75d91demturk /* All the headers should be set now */
a2f9f38db0931e6edf7b71378dd680c3c5fa5841rbb ap_send_http_header(r);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck /* Any data left should now be sent directly */
5babe00918c88eda487771fa6d6d4a1a19c0ced0chuck if (*data)
1ccd992d37d62c8cb2056126f2234f64ec189bfddougm ap_rputs(data, r);
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
2e41eca72bcc4167d1871b0941ee79845540d58eminfrin return TRUE;
0f081398cf0eef8cc7c66a535d450110a92dc8aefielding
35c9e4d2c0a6465746a98958ef756114834461e6minfrin case HSE_REQ_CLOSE_CONNECTION: /* Added after ISAPI 4.0 */
35c9e4d2c0a6465746a98958ef756114834461e6minfrin SetLastError(ERROR_INVALID_PARAMETER);
5a5a6c22260854843c973e2ea9a14bec64362ab5wrowe return FALSE;
d75bc22ab2702fa770f6935f07107efff16a76f0wrowe
00b70ae978854b5eb51722cbeda99c9067b5faf2mturk case HSE_REQ_IS_CONNECTED: /* Added after ISAPI 4.0 */
e2458a81ee951feeff648c2ca5cad2c5a744d8e5mturk /* Returns True if client is connected c.f. Q188346*/
11c3b5180e1de6776035320b012a28bb146e7b46chuck return TRUE;
35c9e4d2c0a6465746a98958ef756114834461e6minfrin
45dac0729754e413ff7c673481b219e9ab1a11f1bnicholes /* case HSE_REQ_EXTENSION_TRIGGER:
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard * Added after ISAPI 4.0?
11c3b5180e1de6776035320b012a28bb146e7b46chuck * Undocumented - from the Microsoft Jan '00 Platform SDK
35c9e4d2c0a6465746a98958ef756114834461e6minfrin */
35c9e4d2c0a6465746a98958ef756114834461e6minfrin default:
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard /* TODO: log unrecognized ServerSupportCommand for debugging
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard */
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin SetLastError(ERROR_INVALID_PARAMETER);
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin return FALSE;
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard }
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddardhandler_rec isapi_handlers[] = {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard { "isapi-isa", isapi_handler },
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard { NULL}
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard};
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrinmodule isapi_module = {
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard STANDARD20_MODULE_STUFF,
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard NULL, /* create per-dir config */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard NULL, /* merge per-dir config */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard NULL, /* server config */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard NULL, /* merge server config */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard NULL, /* command ap_table_t */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard isapi_handlers, /* handlers */
e2b2e15108eb7cb566b1d70ce4e479276d951de5minfrin NULL /* register hooks */
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard};
e6366481b8fe06a24337f0b30b7da66cf64d6062stoddard