module isapi_module;
-static DWORD ReadAheadBuffer = 49152;
-static int LogNotSupported = -1;
-static int AppendLogToErrors = 0;
-static int AppendLogToQuery = 0;
-
/* Declare the ISAPI functions */
BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName,
*/
#pragma optimize("y",off)
+/* Our isapi server config structure */
+
+typedef struct {
+ HANDLE lock;
+ apr_array_header_t *loaded;
+ DWORD ReadAheadBuffer;
+ int LogNotSupported;
+ int AppendLogToErrors;
+ int AppendLogToQuery;
+} isapi_server_conf;
+
/* Our loaded isapi module description structure */
typedef struct {
typedef struct {
LPEXTENSION_CONTROL_BLOCK ecb;
+ isapi_server_conf *sconf;
isapi_loaded *isa;
request_rec *r;
PFN_HSE_IO_COMPLETION completion;
PVOID completion_arg;
HANDLE complete;
- apr_status_t retval;
} isapi_cid;
-apr_status_t isapi_handler (request_rec *r)
+apr_status_t isapi_load(request_rec *r, isapi_loaded** isa);
+BOOL isapi_unload(isapi_loaded* isa, int force);
+
+static apr_status_t cleanup_server_config(void *sconfv)
{
- apr_table_t *e = r->subprocess_env;
+ isapi_server_conf *sconf = sconfv;
+ size_t n;
isapi_loaded *isa;
- isapi_cid *cid;
- DWORD read;
- char *fspec;
- char *p;
- int res;
+
+ n = sconf->loaded->nelts;
+ isa = (isapi_loaded *)sconf->loaded->elts;
+ while(n--) {
+ if (isa->handle)
+ isapi_unload(isa, TRUE);
+ }
+ CloseHandle(sconf->lock);
+ return APR_SUCCESS;
+}
- /* Use similar restrictions as CGIs
- *
- * If this fails, it's pointless to load the isapi dll.
- */
- if (!(ap_allow_options(r) & OPT_EXECCGI))
- return HTTP_FORBIDDEN;
+static void *create_server_config(apr_pool_t *p, server_rec *s)
+{
+ isapi_server_conf *sconf = apr_palloc(p, sizeof(isapi_server_conf*));
+ sconf->loaded = apr_make_array(p, 20, sizeof(isapi_loaded*));
+ sconf->lock = CreateMutex(NULL, FALSE, NULL);
- if (r->finfo.filetype == APR_NOFILE)
- return HTTP_NOT_FOUND;
+ sconf->ReadAheadBuffer = 49152;
+ sconf->LogNotSupported = -1;
+ sconf->AppendLogToErrors = 0;
+ sconf->AppendLogToQuery = 0;
- if (r->finfo.filetype != APR_REG)
- return HTTP_FORBIDDEN;
+ return sconf;
+}
- /* Load the module...
- * per PR2555, the LoadLibraryEx function is very picky about slashes.
+static apr_status_t isapi_load(request_rec *r, isapi_loaded** isa)
+{
+ char *fspec;
+ char *p;
+ /* Per PR2555, the LoadLibraryEx function is very picky about slashes.
* Debugging on NT 4 SP 6a reveals First Chance Exception within NTDLL.
* LoadLibrary in the MS PSDK also reveals that it -explicitly- states
* that backslashes must be used.
++p;
}
- /* Load the module
- *
- * TODO: Critical section
+ /* TODO: Critical section
*
- * Warning: cid should not be allocated from request pool if we
+ * Warning: cid should not be allocated from pool if we
* cache the isapi process in-memory.
*
* This code could use cacheing... everything that follows
* should only be performed on the first isapi dll invocation,
* not with every HttpExtensionProc()
*/
- isa = apr_pcalloc(r->pool, sizeof(isapi_module));
- isa->pVer = apr_pcalloc(r->pool, sizeof(HSE_VERSION_INFO));
- isa->refcount = 0;
+ *isa = apr_pcalloc(r->pool, sizeof(isapi_module));
+ (*isa)->pVer = apr_pcalloc(r->pool, sizeof(HSE_VERSION_INFO));
+ (*isa)->refcount = 1;
/* TODO: These may need to become overrideable, so that we
* assure a given isapi can be fooled into behaving well.
*/
- isa->timeout = INFINITE; /* microsecs */
- isa->fakeasync = TRUE;
- isa->reportversion = MAKELONG(0, 5); /* Revision 5.0 */
+ (*isa)->timeout = INFINITE; /* microsecs */
+ (*isa)->fakeasync = TRUE;
+ (*isa)->reportversion = MAKELONG(0, 5); /* Revision 5.0 */
- if (!(isa->handle = LoadLibraryEx(r->filename, NULL,
- LOAD_WITH_ALTERED_SEARCH_PATH))) {
+ if (!((*isa)->handle = LoadLibraryEx(r->filename, NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH)))
+ {
+ apr_status_t rv = GetLastError();
ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
"ISAPI %s failed to load", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
+ (*isa)->handle = NULL;
+ (*isa)->refcount = 0;
+ return rv;
}
- if (!(isa->GetExtensionVersion =
- (void *)(GetProcAddress(isa->handle, "GetExtensionVersion")))) {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
+ if (!((*isa)->GetExtensionVersion = (void *)(GetProcAddress((*isa)->handle,
+ "GetExtensionVersion"))))
+ {
+ apr_status_t rv = GetLastError();
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
"ISAPI %s is missing GetExtensionVersion()",
r->filename);
- FreeLibrary(isa->handle);
- return HTTP_INTERNAL_SERVER_ERROR;
+ FreeLibrary((*isa)->handle);
+ (*isa)->handle = NULL;
+ (*isa)->refcount = 0;
+ return rv;
}
- if (!(isa->HttpExtensionProc =
- (void *)(GetProcAddress(isa->handle, "HttpExtensionProc")))) {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
+ if (!((*isa)->HttpExtensionProc = (void *)(GetProcAddress((*isa)->handle,
+ "HttpExtensionProc"))))
+ {
+ apr_status_t rv = GetLastError();
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
"ISAPI %s is missing HttpExtensionProc()",
r->filename);
- FreeLibrary(isa->handle);
- return HTTP_INTERNAL_SERVER_ERROR;
+ FreeLibrary((*isa)->handle);
+ (*isa)->handle = NULL;
+ (*isa)->refcount = 0;
+ return rv;
}
/* TerminateExtension() is an optional interface */
-
- isa->TerminateExtension = (void *)(GetProcAddress(isa->handle, "TerminateExtension"));
+ (*isa)->TerminateExtension = (void *)(GetProcAddress((*isa)->handle,
+ "TerminateExtension"));
+ SetLastError(0);
/* Run GetExtensionVersion() */
-
- if (!(*isa->GetExtensionVersion)(isa->pVer)) {
- /* ### euh... we're passing the wrong type of error code here */
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, HTTP_INTERNAL_SERVER_ERROR, r,
+ if (!((*isa)->GetExtensionVersion)((*isa)->pVer)) {
+ apr_status_t rv = GetLastError();
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
"ISAPI %s call GetExtensionVersion() failed",
r->filename);
- FreeLibrary(isa->handle);
- return HTTP_INTERNAL_SERVER_ERROR;
+ FreeLibrary((*isa)->handle);
+ (*isa)->handle = NULL;
+ (*isa)->refcount = 0;
+ return rv;
}
- /* Load of this module completed, this is the point at which *isa
- * could be cached for later invocation.
+ /* If we succeeded at caching this module - the first module needs to
+ * register a cleanup to be polite.
+ */
+ /* if (!sconf->loaded->nelts)
+ * apr_register_cleanup(p, sconf, cleanup_server_config, apr_null_cleanup);
+ */
+
+ return APR_SUCCESS;
+}
+
+static int isapi_unload(isapi_loaded* isa, int force)
+{
+ /* All done with the DLL... get rid of it...
*
- * on to invoking this request...
+ * If optionally cached, pass HSE_TERM_ADVISORY_UNLOAD,
+ * and if it returns TRUE, unload, otherwise, cache it.
*/
+ if ((--isa->refcount > 0) && !force)
+ return FALSE;
+ if (isa->TerminateExtension) {
+ if (force)
+ (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
+ else if (!(*isa->TerminateExtension)(HSE_TERM_ADVISORY_UNLOAD))
+ return FALSE;
+ }
+ FreeLibrary(isa->handle);
+ isa->handle = NULL;
+ return TRUE;
+}
+
+apr_status_t isapi_handler (request_rec *r)
+{
+ apr_table_t *e = r->subprocess_env;
+ apr_status_t rv;
+ isapi_loaded *isa;
+ isapi_cid *cid;
+ DWORD read;
+ int res;
+ /* Use similar restrictions as CGIs
+ *
+ * If this fails, it's pointless to load the isapi dll.
+ */
+ if (!(ap_allow_options(r) & OPT_EXECCGI))
+ return HTTP_FORBIDDEN;
+
+ if (r->finfo.filetype == APR_NOFILE)
+ return HTTP_NOT_FOUND;
+
+ if (r->finfo.filetype != APR_REG)
+ return HTTP_FORBIDDEN;
+
+ /* Load and cache or retrieve the cached extention */
+ if (isapi_load(r, &isa) != APR_SUCCESS)
+ return HTTP_INTERNAL_SERVER_ERROR;
+
/* Set up variables */
ap_add_common_vars(r);
ap_add_cgi_vars(r);
/* Set up connection structure and ecb */
cid = apr_pcalloc(r->pool, sizeof(isapi_cid));
+ cid->sconf = ap_get_module_config(r->server->module_config, &isapi_module);
+
cid->ecb = apr_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK));
cid->ecb->ConnID = (HCONN)cid;
- /* TODO: Critical section */
- ++isa->refcount;
cid->isa = isa;
cid->r = r;
cid->r->status = 0;
cid->complete = NULL;
cid->completion = NULL;
- cid->retval = APR_SUCCESS;
-
+
cid->ecb->cbSize = sizeof(EXTENSION_CONTROL_BLOCK);
cid->ecb->dwVersion = isa->reportversion;
cid->ecb->dwHttpStatusCode = 0;
cid->ecb->lpszContentType = apr_pstrdup(r->pool,
(char*) apr_table_get(e, "CONTENT_TYPE"));
/* Set up the callbacks */
- cid->ecb->GetServerVariable = &GetServerVariable;
- cid->ecb->WriteClient = &WriteClient;
- cid->ecb->ReadClient = &ReadClient;
- cid->ecb->ServerSupportFunction = &ServerSupportFunction;
+ cid->ecb->GetServerVariable = GetServerVariable;
+ cid->ecb->WriteClient = WriteClient;
+ cid->ecb->ReadClient = ReadClient;
+ cid->ecb->ServerSupportFunction = ServerSupportFunction;
/* Set up client input */
- cid->retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
- if (cid->retval) {
- if (isa->TerminateExtension) {
- (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
- }
- FreeLibrary(isa->handle);
- return cid->retval;
+ rv = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
+ if (rv) {
+ isapi_unload(isa, FALSE);
+ return HTTP_INTERNAL_SERVER_ERROR; /* XXX: The wrong error */
}
if (ap_should_client_block(r)) {
*/
if (r->remaining) {
cid->ecb->cbTotalBytes = r->remaining;
- if (cid->ecb->cbTotalBytes > ReadAheadBuffer)
- cid->ecb->cbAvailable = ReadAheadBuffer;
+ if (cid->ecb->cbTotalBytes > cid->sconf->ReadAheadBuffer)
+ cid->ecb->cbAvailable = cid->sconf->ReadAheadBuffer;
else
cid->ecb->cbAvailable = cid->ecb->cbTotalBytes;
}
else
{
cid->ecb->cbTotalBytes = 0xffffffff;
- cid->ecb->cbAvailable = ReadAheadBuffer;
+ cid->ecb->cbAvailable = cid->sconf->ReadAheadBuffer;
}
cid->ecb->lpbData = apr_pcalloc(r->pool, cid->ecb->cbAvailable + 1);
- p = cid->ecb->lpbData;
read = 0;
while (read < cid->ecb->cbAvailable &&
((res = ap_get_client_block(r, cid->ecb->lpbData + read,
- cid->ecb->cbAvailable - read)) > 0)) {
+ cid->ecb->cbAvailable - read)) > 0)) {
read += res;
}
if (res < 0) {
- cid->retval = HTTP_INTERNAL_SERVER_ERROR;
- goto contentfailure;
+ isapi_unload(isa, FALSE);
+ return HTTP_INTERNAL_SERVER_ERROR;
}
/* Although its not to spec, IIS seems to null-terminate
}
/* All right... try and run the sucker */
- cid->retval = (*isa->HttpExtensionProc)(cid->ecb);
-
- /* Set the status (for logging) */
- if (cid->ecb->dwHttpStatusCode) {
- cid->r->status = cid->ecb->dwHttpStatusCode;
- }
+ rv = (*isa->HttpExtensionProc)(cid->ecb);
/* Check for a log message - and log it */
if (cid->ecb->lpszLogData && *cid->ecb->lpszLogData)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
"ISAPI %s: %s", r->filename, cid->ecb->lpszLogData);
- switch(cid->retval) {
+ switch(rv) {
case HSE_STATUS_SUCCESS:
case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
/* Ignore the keepalive stuff; Apache handles it just fine without
*/
if (!isa->fakeasync) {
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
{
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI %s asynch I/O request refused",
r->filename);
- cid->retval = APR_ENOTIMPL;
+ cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
}
}
else {
case HSE_STATUS_ERROR:
/* end response if we have yet to do so.
*/
- cid->retval = HTTP_INTERNAL_SERVER_ERROR;
+ cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
break;
default:
/* TODO: log unrecognized retval for debugging
*/
- cid->retval = HTTP_INTERNAL_SERVER_ERROR;
+ cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
break;
}
-contentfailure:
- /* All done with the DLL... get rid of it...
- *
- * If optionally cached, pass HSE_TERM_ADVISORY_UNLOAD,
- * and if it returns TRUE, unload, otherwise, cache it.
- */
- if (isa->TerminateExtension) {
- (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
+ /* Set the status (for logging) */
+ if (cid->ecb->dwHttpStatusCode) {
+ cid->r->status = cid->ecb->dwHttpStatusCode;
}
- FreeLibrary(isa->handle);
- /* TODO: Crit section */
- cid->isa = NULL;
- --isa->refcount;
- isa->handle = NULL;
+
+ /* All done with the DLL... get rid of it... */
+ isapi_unload(isa, FALSE);
- return cid->retval;
+ return OK; /* NOT r->status, even if it has changed. */
}
#pragma optimize("",on)
LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer)
{
request_rec *r = ((isapi_cid *)hConn)->r;
- apr_table_t *e = r->subprocess_env;
const char *result;
- /* Mostly, we just grab it from the environment, but there are
- * a couple of special cases
- */
-
- if (!strcasecmp(lpszVariableName, "UNMAPPED_REMOTE_USER")) {
- /* We don't support NT users, so this is always the same as
- * REMOTE_USER
+ if (!strcmp(lpszVariableName, "ALL_HTTP"))
+ {
+ /* lf delimited, colon split, comma seperated and
+ * null terminated list of HTTP_ vars
*/
- result = apr_table_get(e, "REMOTE_USER");
+ char **env = (char**) apr_table_elts(r->subprocess_env)->elts;
+ int n = apr_table_elts(r->subprocess_env)->nelts;
+ DWORD len = 0;
+ int i = 0;
+
+ while (i < n * 2) {
+ if (!strncmp(env[i], "HTTP_", 5))
+ len += strlen(env[i]) + strlen(env[i + 1]) + 2;
+ i += 2;
+ }
+
+ if (*lpdwSizeofBuffer < len + 1) {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ i = 0;
+ while (i < n * 2) {
+ if (!strncmp(env[i], "HTTP_", 5)) {
+ strcpy(lpvBuffer, env[i]);
+ ((char*)lpvBuffer) += strlen(env[i]);
+ *(((char*)lpvBuffer)++) = ':';
+ strcpy(lpvBuffer, env[i + 1]);
+ ((char*)lpvBuffer) += strlen(env[i + 1]);
+ *(((char*)lpvBuffer)++) = '\n';
+ }
+ i += 2;
+ }
+ *(((char*)lpvBuffer)++) = '\0';
+ *lpdwSizeofBuffer = len;
+ return TRUE;
}
- else if (!strcasecmp(lpszVariableName, "SERVER_PORT_SECURE")) {
- /* Apache doesn't support secure requests inherently, so
- * we have no way of knowing. We'll be conservative, and say
- * all requests are insecure.
+ else if (!strcmp(lpszVariableName, "ALL_RAW"))
+ {
+ /* lf delimited, colon split, comma seperated and
+ * null terminated list of the raw request header
*/
- result = "0";
- }
- else if (!strcasecmp(lpszVariableName, "URL")) {
- result = r->uri;
+ char **raw = (char**) apr_table_elts(r->headers_in)->elts;
+ int n = apr_table_elts(r->headers_in)->nelts;
+ DWORD len = 0;
+ int i = 0;
+
+ while (i < n * 2) {
+ len += strlen(raw[i]) + strlen(raw[i + 1]) + 2;
+ i += 2;
+ }
+
+ if (*lpdwSizeofBuffer < len + 1) {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ i = 0;
+ while (i < n * 2) {
+ strcpy(lpvBuffer, raw[i]);
+ ((char*)lpvBuffer) += strlen(raw[i]);
+ *(((char*)lpvBuffer)++) = ':';
+ *(((char*)lpvBuffer)++) = ' ';
+ strcpy(lpvBuffer, raw[i + 1]);
+ ((char*)lpvBuffer) += strlen(raw[i + 1]);
+ *(((char*)lpvBuffer)++) = '\n';
+ i += 2;
+ }
+ *(((char*)lpvBuffer)++) = '\0';
+ *lpdwSizeofBuffer = len;
+ return TRUE;
}
else {
- result = apr_table_get(e, lpszVariableName);
+ result = apr_table_get(r->subprocess_env, lpszVariableName);
}
if (result) {
return TRUE;
}
- /* Didn't find it */
+ /* Didn't find it - should this be ERROR_NO_DATA? */
SetLastError(ERROR_INVALID_INDEX);
return FALSE;
}
/* We only support synchronous writing */
if (dwReserved && dwReserved != HSE_IO_SYNC) {
- if (LogNotSupported)
+ if (((isapi_cid *)ConnID)->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI %s asynch I/O request refused",
r->filename);
}
/* Parse them out, or die trying */
- cid->retval = ap_scan_script_header_err_strs(cid->r, NULL, &termch,
- &termarg, stat, head, NULL);
+ cid->r->status= ap_scan_script_header_err_strs(cid->r, NULL, &termch,
+ &termarg, stat, head, NULL);
cid->ecb->dwHttpStatusCode = cid->r->status;
-
+ if (cid->r->status == HTTP_INTERNAL_SERVER_ERROR)
+ return FALSE;
+
/* All the headers should be set now */
ap_send_http_header(cid->r);
ap_rwrite(termch, headlen - (termch - head), cid->r);
}
- if (cid->retval == HTTP_INTERNAL_SERVER_ERROR)
- return FALSE;
return TRUE;
}
}
case 1002: /* HSE_REQ_GET_SSPI_INFO */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction HSE_REQ_GET_SSPI_INFO "
"is not supported: %s", r->filename);
/* Log lpvBuffer, of lpdwSize bytes, in the URI Query (cs-uri-query) field
*/
apr_table_set(r->notes, "isapi-parameter", (char*) lpvBuffer);
- if (AppendLogToQuery) {
+ if (cid->sconf->AppendLogToQuery) {
if (r->args)
r->args = apr_pstrcat(r->pool, r->args, (char*) lpvBuffer, NULL);
else
r->args = apr_pstrdup(r->pool, (char*) lpvBuffer);
}
- if (AppendLogToErrors)
+ if (cid->sconf->AppendLogToErrors)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
"ISAPI %s: %s", cid->r->filename,
(char*) lpvBuffer);
return TRUE;
case 1005: /* HSE_REQ_IO_COMPLETION */
- /* TODO: Emulate a completion port, if we can...
- * Record the callback address and user defined argument...
- * we will call this after any async request (e.g. transmitfile)
- * as if the request had completed async execution.
+ /* Emulates a completion port... Record callback address and
+ * user defined arg, we will call this after any async request
+ * (e.g. transmitfile) as if the request executed async.
* Per MS docs... HSE_REQ_IO_COMPLETION replaces any prior call
* to HSE_REQ_IO_COMPLETION, and lpvBuffer may be set to NULL.
*/
* Just not quite ready yet...
*/
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI asynchronous I/O not supported: %s",
r->filename);
return FALSE;
case 1007: /* HSE_REQ_REFRESH_ISAPI_ACL */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_REFRESH_ISAPI_ACL "
return TRUE;
case 1010: /* HSE_REQ_ASYNC_READ_CLIENT */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI asynchronous I/O not supported: %s",
r->filename);
return FALSE;
case 1011: /* HSE_REQ_GET_IMPERSONATION_TOKEN Added in ISAPI 4.0 */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_GET_IMPERSONATION_TOKEN "
}
case 1014: /* HSE_REQ_ABORTIVE_CLOSE */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE"
" is not supported: %s", r->filename);
return FALSE;
case 1015: /* HSE_REQ_GET_CERT_INFO_EX Added in ISAPI 4.0 */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_GET_CERT_INFO_EX "
}
case 1017: /* HSE_REQ_CLOSE_CONNECTION Added after ISAPI 4.0 */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_CLOSE_CONNECTION "
case 1020: /* HSE_REQ_EXTENSION_TRIGGER Added after ISAPI 4.0 */
/* Undocumented - defined by the Microsoft Jan '00 Platform SDK
*/
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_EXTENSION_TRIGGER "
return FALSE;
default:
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction (%d) not supported: "
"%s", dwHSERequest, r->filename);
static const char *isapi_cmd_readaheadbuffer(cmd_parms *cmd, void *config,
char *arg)
{
+ isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
+ &isapi_module);
+ char *scan;
long val;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
- if (((val = strtol(arg, (char **) &err, 10)) <= 0) || *err)
+ if (((val = strtol(arg, (char **) &scan, 10)) <= 0) || *scan)
return "ISAPIReadAheadBuffer must be a legitimate value.";
- ReadAheadBuffer = val;
+ sconf->ReadAheadBuffer = val;
return NULL;
}
static const char *isapi_cmd_lognotsupported(cmd_parms *cmd, void *config,
char *arg)
{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
+ isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
+ &isapi_module);
if (strcasecmp(arg, "on") == 0) {
- LogNotSupported = -1;
+ sconf->LogNotSupported = -1;
}
else if (strcasecmp(arg, "off") == 0) {
- LogNotSupported = 0;
+ sconf->LogNotSupported = 0;
}
else {
return "ISAPILogNotSupported must be on or off";
static const char *isapi_cmd_appendlogtoerrors(cmd_parms *cmd, void *config,
char *arg)
{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
+ isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
+ &isapi_module);
if (strcasecmp(arg, "on") == 0) {
- AppendLogToErrors = -1;
+ sconf->AppendLogToErrors = -1;
}
else if (strcasecmp(arg, "off") == 0) {
- AppendLogToErrors = 0;
+ sconf->AppendLogToErrors = 0;
}
else {
return "ISAPIAppendLogToErrors must be on or off";
static const char *isapi_cmd_appendlogtoquery(cmd_parms *cmd, void *config,
char *arg)
{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
+ isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
+ &isapi_module);
if (strcasecmp(arg, "on") == 0) {
- AppendLogToQuery = -1;
+ sconf->AppendLogToQuery = -1;
}
else if (strcasecmp(arg, "off") == 0) {
- AppendLogToQuery = 0;
+ sconf->AppendLogToQuery = 0;
}
else {
return "ISAPIAppendLogToQuery must be on or off";
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config */
NULL, /* merge per-dir config */
- NULL, /* server config */
+ create_server_config, /* server config */
NULL, /* merge server config */
isapi_cmds, /* command apr_table_t */
isapi_handlers, /* handlers */
module isapi_module;
-static DWORD ReadAheadBuffer = 49152;
-static int LogNotSupported = -1;
-static int AppendLogToErrors = 0;
-static int AppendLogToQuery = 0;
-
/* Declare the ISAPI functions */
BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName,
*/
#pragma optimize("y",off)
+/* Our isapi server config structure */
+
+typedef struct {
+ HANDLE lock;
+ apr_array_header_t *loaded;
+ DWORD ReadAheadBuffer;
+ int LogNotSupported;
+ int AppendLogToErrors;
+ int AppendLogToQuery;
+} isapi_server_conf;
+
/* Our loaded isapi module description structure */
typedef struct {
typedef struct {
LPEXTENSION_CONTROL_BLOCK ecb;
+ isapi_server_conf *sconf;
isapi_loaded *isa;
request_rec *r;
PFN_HSE_IO_COMPLETION completion;
PVOID completion_arg;
HANDLE complete;
- apr_status_t retval;
} isapi_cid;
-apr_status_t isapi_handler (request_rec *r)
+apr_status_t isapi_load(request_rec *r, isapi_loaded** isa);
+BOOL isapi_unload(isapi_loaded* isa, int force);
+
+static apr_status_t cleanup_server_config(void *sconfv)
{
- apr_table_t *e = r->subprocess_env;
+ isapi_server_conf *sconf = sconfv;
+ size_t n;
isapi_loaded *isa;
- isapi_cid *cid;
- DWORD read;
- char *fspec;
- char *p;
- int res;
+
+ n = sconf->loaded->nelts;
+ isa = (isapi_loaded *)sconf->loaded->elts;
+ while(n--) {
+ if (isa->handle)
+ isapi_unload(isa, TRUE);
+ }
+ CloseHandle(sconf->lock);
+ return APR_SUCCESS;
+}
- /* Use similar restrictions as CGIs
- *
- * If this fails, it's pointless to load the isapi dll.
- */
- if (!(ap_allow_options(r) & OPT_EXECCGI))
- return HTTP_FORBIDDEN;
+static void *create_server_config(apr_pool_t *p, server_rec *s)
+{
+ isapi_server_conf *sconf = apr_palloc(p, sizeof(isapi_server_conf*));
+ sconf->loaded = apr_make_array(p, 20, sizeof(isapi_loaded*));
+ sconf->lock = CreateMutex(NULL, FALSE, NULL);
- if (r->finfo.filetype == APR_NOFILE)
- return HTTP_NOT_FOUND;
+ sconf->ReadAheadBuffer = 49152;
+ sconf->LogNotSupported = -1;
+ sconf->AppendLogToErrors = 0;
+ sconf->AppendLogToQuery = 0;
- if (r->finfo.filetype != APR_REG)
- return HTTP_FORBIDDEN;
+ return sconf;
+}
- /* Load the module...
- * per PR2555, the LoadLibraryEx function is very picky about slashes.
+static apr_status_t isapi_load(request_rec *r, isapi_loaded** isa)
+{
+ char *fspec;
+ char *p;
+ /* Per PR2555, the LoadLibraryEx function is very picky about slashes.
* Debugging on NT 4 SP 6a reveals First Chance Exception within NTDLL.
* LoadLibrary in the MS PSDK also reveals that it -explicitly- states
* that backslashes must be used.
++p;
}
- /* Load the module
- *
- * TODO: Critical section
+ /* TODO: Critical section
*
- * Warning: cid should not be allocated from request pool if we
+ * Warning: cid should not be allocated from pool if we
* cache the isapi process in-memory.
*
* This code could use cacheing... everything that follows
* should only be performed on the first isapi dll invocation,
* not with every HttpExtensionProc()
*/
- isa = apr_pcalloc(r->pool, sizeof(isapi_module));
- isa->pVer = apr_pcalloc(r->pool, sizeof(HSE_VERSION_INFO));
- isa->refcount = 0;
+ *isa = apr_pcalloc(r->pool, sizeof(isapi_module));
+ (*isa)->pVer = apr_pcalloc(r->pool, sizeof(HSE_VERSION_INFO));
+ (*isa)->refcount = 1;
/* TODO: These may need to become overrideable, so that we
* assure a given isapi can be fooled into behaving well.
*/
- isa->timeout = INFINITE; /* microsecs */
- isa->fakeasync = TRUE;
- isa->reportversion = MAKELONG(0, 5); /* Revision 5.0 */
+ (*isa)->timeout = INFINITE; /* microsecs */
+ (*isa)->fakeasync = TRUE;
+ (*isa)->reportversion = MAKELONG(0, 5); /* Revision 5.0 */
- if (!(isa->handle = LoadLibraryEx(r->filename, NULL,
- LOAD_WITH_ALTERED_SEARCH_PATH))) {
+ if (!((*isa)->handle = LoadLibraryEx(r->filename, NULL,
+ LOAD_WITH_ALTERED_SEARCH_PATH)))
+ {
+ apr_status_t rv = GetLastError();
ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
"ISAPI %s failed to load", r->filename);
- return HTTP_INTERNAL_SERVER_ERROR;
+ (*isa)->handle = NULL;
+ (*isa)->refcount = 0;
+ return rv;
}
- if (!(isa->GetExtensionVersion =
- (void *)(GetProcAddress(isa->handle, "GetExtensionVersion")))) {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
+ if (!((*isa)->GetExtensionVersion = (void *)(GetProcAddress((*isa)->handle,
+ "GetExtensionVersion"))))
+ {
+ apr_status_t rv = GetLastError();
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
"ISAPI %s is missing GetExtensionVersion()",
r->filename);
- FreeLibrary(isa->handle);
- return HTTP_INTERNAL_SERVER_ERROR;
+ FreeLibrary((*isa)->handle);
+ (*isa)->handle = NULL;
+ (*isa)->refcount = 0;
+ return rv;
}
- if (!(isa->HttpExtensionProc =
- (void *)(GetProcAddress(isa->handle, "HttpExtensionProc")))) {
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, GetLastError(), r,
+ if (!((*isa)->HttpExtensionProc = (void *)(GetProcAddress((*isa)->handle,
+ "HttpExtensionProc"))))
+ {
+ apr_status_t rv = GetLastError();
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
"ISAPI %s is missing HttpExtensionProc()",
r->filename);
- FreeLibrary(isa->handle);
- return HTTP_INTERNAL_SERVER_ERROR;
+ FreeLibrary((*isa)->handle);
+ (*isa)->handle = NULL;
+ (*isa)->refcount = 0;
+ return rv;
}
/* TerminateExtension() is an optional interface */
-
- isa->TerminateExtension = (void *)(GetProcAddress(isa->handle, "TerminateExtension"));
+ (*isa)->TerminateExtension = (void *)(GetProcAddress((*isa)->handle,
+ "TerminateExtension"));
+ SetLastError(0);
/* Run GetExtensionVersion() */
-
- if (!(*isa->GetExtensionVersion)(isa->pVer)) {
- /* ### euh... we're passing the wrong type of error code here */
- ap_log_rerror(APLOG_MARK, APLOG_ALERT, HTTP_INTERNAL_SERVER_ERROR, r,
+ if (!((*isa)->GetExtensionVersion)((*isa)->pVer)) {
+ apr_status_t rv = GetLastError();
+ ap_log_rerror(APLOG_MARK, APLOG_ALERT, rv, r,
"ISAPI %s call GetExtensionVersion() failed",
r->filename);
- FreeLibrary(isa->handle);
- return HTTP_INTERNAL_SERVER_ERROR;
+ FreeLibrary((*isa)->handle);
+ (*isa)->handle = NULL;
+ (*isa)->refcount = 0;
+ return rv;
}
- /* Load of this module completed, this is the point at which *isa
- * could be cached for later invocation.
+ /* If we succeeded at caching this module - the first module needs to
+ * register a cleanup to be polite.
+ */
+ /* if (!sconf->loaded->nelts)
+ * apr_register_cleanup(p, sconf, cleanup_server_config, apr_null_cleanup);
+ */
+
+ return APR_SUCCESS;
+}
+
+static int isapi_unload(isapi_loaded* isa, int force)
+{
+ /* All done with the DLL... get rid of it...
*
- * on to invoking this request...
+ * If optionally cached, pass HSE_TERM_ADVISORY_UNLOAD,
+ * and if it returns TRUE, unload, otherwise, cache it.
*/
+ if ((--isa->refcount > 0) && !force)
+ return FALSE;
+ if (isa->TerminateExtension) {
+ if (force)
+ (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
+ else if (!(*isa->TerminateExtension)(HSE_TERM_ADVISORY_UNLOAD))
+ return FALSE;
+ }
+ FreeLibrary(isa->handle);
+ isa->handle = NULL;
+ return TRUE;
+}
+
+apr_status_t isapi_handler (request_rec *r)
+{
+ apr_table_t *e = r->subprocess_env;
+ apr_status_t rv;
+ isapi_loaded *isa;
+ isapi_cid *cid;
+ DWORD read;
+ int res;
+ /* Use similar restrictions as CGIs
+ *
+ * If this fails, it's pointless to load the isapi dll.
+ */
+ if (!(ap_allow_options(r) & OPT_EXECCGI))
+ return HTTP_FORBIDDEN;
+
+ if (r->finfo.filetype == APR_NOFILE)
+ return HTTP_NOT_FOUND;
+
+ if (r->finfo.filetype != APR_REG)
+ return HTTP_FORBIDDEN;
+
+ /* Load and cache or retrieve the cached extention */
+ if (isapi_load(r, &isa) != APR_SUCCESS)
+ return HTTP_INTERNAL_SERVER_ERROR;
+
/* Set up variables */
ap_add_common_vars(r);
ap_add_cgi_vars(r);
/* Set up connection structure and ecb */
cid = apr_pcalloc(r->pool, sizeof(isapi_cid));
+ cid->sconf = ap_get_module_config(r->server->module_config, &isapi_module);
+
cid->ecb = apr_pcalloc(r->pool, sizeof(struct _EXTENSION_CONTROL_BLOCK));
cid->ecb->ConnID = (HCONN)cid;
- /* TODO: Critical section */
- ++isa->refcount;
cid->isa = isa;
cid->r = r;
cid->r->status = 0;
cid->complete = NULL;
cid->completion = NULL;
- cid->retval = APR_SUCCESS;
-
+
cid->ecb->cbSize = sizeof(EXTENSION_CONTROL_BLOCK);
cid->ecb->dwVersion = isa->reportversion;
cid->ecb->dwHttpStatusCode = 0;
cid->ecb->lpszContentType = apr_pstrdup(r->pool,
(char*) apr_table_get(e, "CONTENT_TYPE"));
/* Set up the callbacks */
- cid->ecb->GetServerVariable = &GetServerVariable;
- cid->ecb->WriteClient = &WriteClient;
- cid->ecb->ReadClient = &ReadClient;
- cid->ecb->ServerSupportFunction = &ServerSupportFunction;
+ cid->ecb->GetServerVariable = GetServerVariable;
+ cid->ecb->WriteClient = WriteClient;
+ cid->ecb->ReadClient = ReadClient;
+ cid->ecb->ServerSupportFunction = ServerSupportFunction;
/* Set up client input */
- cid->retval = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
- if (cid->retval) {
- if (isa->TerminateExtension) {
- (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
- }
- FreeLibrary(isa->handle);
- return cid->retval;
+ rv = ap_setup_client_block(r, REQUEST_CHUNKED_ERROR);
+ if (rv) {
+ isapi_unload(isa, FALSE);
+ return HTTP_INTERNAL_SERVER_ERROR; /* XXX: The wrong error */
}
if (ap_should_client_block(r)) {
*/
if (r->remaining) {
cid->ecb->cbTotalBytes = r->remaining;
- if (cid->ecb->cbTotalBytes > ReadAheadBuffer)
- cid->ecb->cbAvailable = ReadAheadBuffer;
+ if (cid->ecb->cbTotalBytes > cid->sconf->ReadAheadBuffer)
+ cid->ecb->cbAvailable = cid->sconf->ReadAheadBuffer;
else
cid->ecb->cbAvailable = cid->ecb->cbTotalBytes;
}
else
{
cid->ecb->cbTotalBytes = 0xffffffff;
- cid->ecb->cbAvailable = ReadAheadBuffer;
+ cid->ecb->cbAvailable = cid->sconf->ReadAheadBuffer;
}
cid->ecb->lpbData = apr_pcalloc(r->pool, cid->ecb->cbAvailable + 1);
- p = cid->ecb->lpbData;
read = 0;
while (read < cid->ecb->cbAvailable &&
((res = ap_get_client_block(r, cid->ecb->lpbData + read,
- cid->ecb->cbAvailable - read)) > 0)) {
+ cid->ecb->cbAvailable - read)) > 0)) {
read += res;
}
if (res < 0) {
- cid->retval = HTTP_INTERNAL_SERVER_ERROR;
- goto contentfailure;
+ isapi_unload(isa, FALSE);
+ return HTTP_INTERNAL_SERVER_ERROR;
}
/* Although its not to spec, IIS seems to null-terminate
}
/* All right... try and run the sucker */
- cid->retval = (*isa->HttpExtensionProc)(cid->ecb);
-
- /* Set the status (for logging) */
- if (cid->ecb->dwHttpStatusCode) {
- cid->r->status = cid->ecb->dwHttpStatusCode;
- }
+ rv = (*isa->HttpExtensionProc)(cid->ecb);
/* Check for a log message - and log it */
if (cid->ecb->lpszLogData && *cid->ecb->lpszLogData)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
"ISAPI %s: %s", r->filename, cid->ecb->lpszLogData);
- switch(cid->retval) {
+ switch(rv) {
case HSE_STATUS_SUCCESS:
case HSE_STATUS_SUCCESS_AND_KEEP_CONN:
/* Ignore the keepalive stuff; Apache handles it just fine without
*/
if (!isa->fakeasync) {
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
{
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI %s asynch I/O request refused",
r->filename);
- cid->retval = APR_ENOTIMPL;
+ cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
}
}
else {
case HSE_STATUS_ERROR:
/* end response if we have yet to do so.
*/
- cid->retval = HTTP_INTERNAL_SERVER_ERROR;
+ cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
break;
default:
/* TODO: log unrecognized retval for debugging
*/
- cid->retval = HTTP_INTERNAL_SERVER_ERROR;
+ cid->r->status = HTTP_INTERNAL_SERVER_ERROR;
break;
}
-contentfailure:
- /* All done with the DLL... get rid of it...
- *
- * If optionally cached, pass HSE_TERM_ADVISORY_UNLOAD,
- * and if it returns TRUE, unload, otherwise, cache it.
- */
- if (isa->TerminateExtension) {
- (*isa->TerminateExtension)(HSE_TERM_MUST_UNLOAD);
+ /* Set the status (for logging) */
+ if (cid->ecb->dwHttpStatusCode) {
+ cid->r->status = cid->ecb->dwHttpStatusCode;
}
- FreeLibrary(isa->handle);
- /* TODO: Crit section */
- cid->isa = NULL;
- --isa->refcount;
- isa->handle = NULL;
+
+ /* All done with the DLL... get rid of it... */
+ isapi_unload(isa, FALSE);
- return cid->retval;
+ return OK; /* NOT r->status, even if it has changed. */
}
#pragma optimize("",on)
LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer)
{
request_rec *r = ((isapi_cid *)hConn)->r;
- apr_table_t *e = r->subprocess_env;
const char *result;
- /* Mostly, we just grab it from the environment, but there are
- * a couple of special cases
- */
-
- if (!strcasecmp(lpszVariableName, "UNMAPPED_REMOTE_USER")) {
- /* We don't support NT users, so this is always the same as
- * REMOTE_USER
+ if (!strcmp(lpszVariableName, "ALL_HTTP"))
+ {
+ /* lf delimited, colon split, comma seperated and
+ * null terminated list of HTTP_ vars
*/
- result = apr_table_get(e, "REMOTE_USER");
+ char **env = (char**) apr_table_elts(r->subprocess_env)->elts;
+ int n = apr_table_elts(r->subprocess_env)->nelts;
+ DWORD len = 0;
+ int i = 0;
+
+ while (i < n * 2) {
+ if (!strncmp(env[i], "HTTP_", 5))
+ len += strlen(env[i]) + strlen(env[i + 1]) + 2;
+ i += 2;
+ }
+
+ if (*lpdwSizeofBuffer < len + 1) {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ i = 0;
+ while (i < n * 2) {
+ if (!strncmp(env[i], "HTTP_", 5)) {
+ strcpy(lpvBuffer, env[i]);
+ ((char*)lpvBuffer) += strlen(env[i]);
+ *(((char*)lpvBuffer)++) = ':';
+ strcpy(lpvBuffer, env[i + 1]);
+ ((char*)lpvBuffer) += strlen(env[i + 1]);
+ *(((char*)lpvBuffer)++) = '\n';
+ }
+ i += 2;
+ }
+ *(((char*)lpvBuffer)++) = '\0';
+ *lpdwSizeofBuffer = len;
+ return TRUE;
}
- else if (!strcasecmp(lpszVariableName, "SERVER_PORT_SECURE")) {
- /* Apache doesn't support secure requests inherently, so
- * we have no way of knowing. We'll be conservative, and say
- * all requests are insecure.
+ else if (!strcmp(lpszVariableName, "ALL_RAW"))
+ {
+ /* lf delimited, colon split, comma seperated and
+ * null terminated list of the raw request header
*/
- result = "0";
- }
- else if (!strcasecmp(lpszVariableName, "URL")) {
- result = r->uri;
+ char **raw = (char**) apr_table_elts(r->headers_in)->elts;
+ int n = apr_table_elts(r->headers_in)->nelts;
+ DWORD len = 0;
+ int i = 0;
+
+ while (i < n * 2) {
+ len += strlen(raw[i]) + strlen(raw[i + 1]) + 2;
+ i += 2;
+ }
+
+ if (*lpdwSizeofBuffer < len + 1) {
+ SetLastError(ERROR_INSUFFICIENT_BUFFER);
+ return FALSE;
+ }
+
+ i = 0;
+ while (i < n * 2) {
+ strcpy(lpvBuffer, raw[i]);
+ ((char*)lpvBuffer) += strlen(raw[i]);
+ *(((char*)lpvBuffer)++) = ':';
+ *(((char*)lpvBuffer)++) = ' ';
+ strcpy(lpvBuffer, raw[i + 1]);
+ ((char*)lpvBuffer) += strlen(raw[i + 1]);
+ *(((char*)lpvBuffer)++) = '\n';
+ i += 2;
+ }
+ *(((char*)lpvBuffer)++) = '\0';
+ *lpdwSizeofBuffer = len;
+ return TRUE;
}
else {
- result = apr_table_get(e, lpszVariableName);
+ result = apr_table_get(r->subprocess_env, lpszVariableName);
}
if (result) {
return TRUE;
}
- /* Didn't find it */
+ /* Didn't find it - should this be ERROR_NO_DATA? */
SetLastError(ERROR_INVALID_INDEX);
return FALSE;
}
/* We only support synchronous writing */
if (dwReserved && dwReserved != HSE_IO_SYNC) {
- if (LogNotSupported)
+ if (((isapi_cid *)ConnID)->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI %s asynch I/O request refused",
r->filename);
}
/* Parse them out, or die trying */
- cid->retval = ap_scan_script_header_err_strs(cid->r, NULL, &termch,
- &termarg, stat, head, NULL);
+ cid->r->status= ap_scan_script_header_err_strs(cid->r, NULL, &termch,
+ &termarg, stat, head, NULL);
cid->ecb->dwHttpStatusCode = cid->r->status;
-
+ if (cid->r->status == HTTP_INTERNAL_SERVER_ERROR)
+ return FALSE;
+
/* All the headers should be set now */
ap_send_http_header(cid->r);
ap_rwrite(termch, headlen - (termch - head), cid->r);
}
- if (cid->retval == HTTP_INTERNAL_SERVER_ERROR)
- return FALSE;
return TRUE;
}
}
case 1002: /* HSE_REQ_GET_SSPI_INFO */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction HSE_REQ_GET_SSPI_INFO "
"is not supported: %s", r->filename);
/* Log lpvBuffer, of lpdwSize bytes, in the URI Query (cs-uri-query) field
*/
apr_table_set(r->notes, "isapi-parameter", (char*) lpvBuffer);
- if (AppendLogToQuery) {
+ if (cid->sconf->AppendLogToQuery) {
if (r->args)
r->args = apr_pstrcat(r->pool, r->args, (char*) lpvBuffer, NULL);
else
r->args = apr_pstrdup(r->pool, (char*) lpvBuffer);
}
- if (AppendLogToErrors)
+ if (cid->sconf->AppendLogToErrors)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_INFO, 0, r,
"ISAPI %s: %s", cid->r->filename,
(char*) lpvBuffer);
return TRUE;
case 1005: /* HSE_REQ_IO_COMPLETION */
- /* TODO: Emulate a completion port, if we can...
- * Record the callback address and user defined argument...
- * we will call this after any async request (e.g. transmitfile)
- * as if the request had completed async execution.
+ /* Emulates a completion port... Record callback address and
+ * user defined arg, we will call this after any async request
+ * (e.g. transmitfile) as if the request executed async.
* Per MS docs... HSE_REQ_IO_COMPLETION replaces any prior call
* to HSE_REQ_IO_COMPLETION, and lpvBuffer may be set to NULL.
*/
* Just not quite ready yet...
*/
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI asynchronous I/O not supported: %s",
r->filename);
return FALSE;
case 1007: /* HSE_REQ_REFRESH_ISAPI_ACL */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_REFRESH_ISAPI_ACL "
return TRUE;
case 1010: /* HSE_REQ_ASYNC_READ_CLIENT */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI asynchronous I/O not supported: %s",
r->filename);
return FALSE;
case 1011: /* HSE_REQ_GET_IMPERSONATION_TOKEN Added in ISAPI 4.0 */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_GET_IMPERSONATION_TOKEN "
}
case 1014: /* HSE_REQ_ABORTIVE_CLOSE */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction HSE_REQ_ABORTIVE_CLOSE"
" is not supported: %s", r->filename);
return FALSE;
case 1015: /* HSE_REQ_GET_CERT_INFO_EX Added in ISAPI 4.0 */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_GET_CERT_INFO_EX "
}
case 1017: /* HSE_REQ_CLOSE_CONNECTION Added after ISAPI 4.0 */
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_CLOSE_CONNECTION "
case 1020: /* HSE_REQ_EXTENSION_TRIGGER Added after ISAPI 4.0 */
/* Undocumented - defined by the Microsoft Jan '00 Platform SDK
*/
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction "
"HSE_REQ_EXTENSION_TRIGGER "
return FALSE;
default:
- if (LogNotSupported)
+ if (cid->sconf->LogNotSupported)
ap_log_rerror(APLOG_MARK, APLOG_NOERRNO|APLOG_WARNING, 0, r,
"ISAPI ServerSupportFunction (%d) not supported: "
"%s", dwHSERequest, r->filename);
static const char *isapi_cmd_readaheadbuffer(cmd_parms *cmd, void *config,
char *arg)
{
+ isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
+ &isapi_module);
+ char *scan;
long val;
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
- if (((val = strtol(arg, (char **) &err, 10)) <= 0) || *err)
+ if (((val = strtol(arg, (char **) &scan, 10)) <= 0) || *scan)
return "ISAPIReadAheadBuffer must be a legitimate value.";
- ReadAheadBuffer = val;
+ sconf->ReadAheadBuffer = val;
return NULL;
}
static const char *isapi_cmd_lognotsupported(cmd_parms *cmd, void *config,
char *arg)
{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
+ isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
+ &isapi_module);
if (strcasecmp(arg, "on") == 0) {
- LogNotSupported = -1;
+ sconf->LogNotSupported = -1;
}
else if (strcasecmp(arg, "off") == 0) {
- LogNotSupported = 0;
+ sconf->LogNotSupported = 0;
}
else {
return "ISAPILogNotSupported must be on or off";
static const char *isapi_cmd_appendlogtoerrors(cmd_parms *cmd, void *config,
char *arg)
{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
+ isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
+ &isapi_module);
if (strcasecmp(arg, "on") == 0) {
- AppendLogToErrors = -1;
+ sconf->AppendLogToErrors = -1;
}
else if (strcasecmp(arg, "off") == 0) {
- AppendLogToErrors = 0;
+ sconf->AppendLogToErrors = 0;
}
else {
return "ISAPIAppendLogToErrors must be on or off";
static const char *isapi_cmd_appendlogtoquery(cmd_parms *cmd, void *config,
char *arg)
{
- const char *err = ap_check_cmd_context(cmd, GLOBAL_ONLY);
- if (err != NULL) {
- return err;
- }
+ isapi_server_conf *sconf = ap_get_module_config(cmd->server->module_config,
+ &isapi_module);
if (strcasecmp(arg, "on") == 0) {
- AppendLogToQuery = -1;
+ sconf->AppendLogToQuery = -1;
}
else if (strcasecmp(arg, "off") == 0) {
- AppendLogToQuery = 0;
+ sconf->AppendLogToQuery = 0;
}
else {
return "ISAPIAppendLogToQuery must be on or off";
STANDARD20_MODULE_STUFF,
NULL, /* create per-dir config */
NULL, /* merge per-dir config */
- NULL, /* server config */
+ create_server_config, /* server config */
NULL, /* merge server config */
isapi_cmds, /* command apr_table_t */
isapi_handlers, /* handlers */