📄 mod_isapi.c
字号:
return APR_SUCCESS;}static int isapi_unload(isapi_loaded* isa, int force){ /* 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->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; } apr_dso_unload(isa->handle); isa->handle = NULL; return TRUE;}apr_status_t isapi_handler (request_rec *r){ isapi_server_conf * sconf; apr_table_t *e; apr_status_t rv; isapi_loaded *isa; isapi_cid *cid; DWORD read; int res; if(strcmp(r->handler, "isapi-isa")) return DECLINED; sconf = ap_get_module_config(r->server->module_config, &isapi_module); e = r->subprocess_env; /* 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 the isapi extention without caching (sconf == NULL) * but note that we will recover an existing cached module. */ if (isapi_load(r->pool, sconf, r, r->filename, &isa) != APR_SUCCESS) return HTTP_INTERNAL_SERVER_ERROR; /* Set up variables */ ap_add_common_vars(r); ap_add_cgi_vars(r); apr_table_setn(r->subprocess_env, "UNMAPPED_REMOTE_USER", "REMOTE_USER"); apr_table_setn(r->subprocess_env, "SERVER_PORT_SECURE", "0"); apr_table_setn(r->subprocess_env, "URL", r->uri); /* 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; cid->isa = isa; cid->r = r; cid->r->status = 0; cid->complete = NULL; cid->completion = NULL; cid->ecb->cbSize = sizeof(EXTENSION_CONTROL_BLOCK); cid->ecb->dwVersion = isa->reportversion; cid->ecb->dwHttpStatusCode = 0; strcpy(cid->ecb->lpszLogData, ""); // TODO: are copies really needed here? cid->ecb->lpszMethod = apr_pstrdup(r->pool, (char*) r->method); cid->ecb->lpszQueryString = apr_pstrdup(r->pool, (char*) apr_table_get(e, "QUERY_STRING")); cid->ecb->lpszPathInfo = apr_pstrdup(r->pool, (char*) apr_table_get(e, "PATH_INFO")); cid->ecb->lpszPathTranslated = apr_pstrdup(r->pool, (char*) apr_table_get(e, "PATH_TRANSLATED")); 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; /* Set up client input */ 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)) { /* Time to start reading the appropriate amount of data, * and allow the administrator to tweak the number * TODO: add the httpd.conf option for ReadAheadBuffer. */ if (r->remaining) { cid->ecb->cbTotalBytes = r->remaining; 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 = cid->sconf->ReadAheadBuffer; } cid->ecb->lpbData = apr_pcalloc(r->pool, cid->ecb->cbAvailable + 1); read = 0; while (read < cid->ecb->cbAvailable && ((res = ap_get_client_block(r, cid->ecb->lpbData + read, cid->ecb->cbAvailable - read)) > 0)) { read += res; } if (res < 0) { isapi_unload(isa, FALSE); return HTTP_INTERNAL_SERVER_ERROR; } /* Although its not to spec, IIS seems to null-terminate * its lpdData string. So we will too. */ if (res == 0) cid->ecb->cbAvailable = cid->ecb->cbTotalBytes = read; else cid->ecb->cbAvailable = read; cid->ecb->lpbData[read] = '\0'; } else { cid->ecb->cbTotalBytes = 0; cid->ecb->cbAvailable = 0; cid->ecb->lpbData = NULL; } /* All right... try and run the sucker */ 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(rv) { case HSE_STATUS_SUCCESS: case HSE_STATUS_SUCCESS_AND_KEEP_CONN: /* Ignore the keepalive stuff; Apache handles it just fine without * the ISA's "advice". * Per Microsoft: "In IIS versions 4.0 and later, the return * values HSE_STATUS_SUCCESS and HSE_STATUS_SUCCESS_AND_KEEP_CONN * are functionally identical: Keep-Alive connections are * maintained, if supported by the client." * ... so we were pat all this time */ break; case HSE_STATUS_PENDING: /* emulating async behavior... * * Create a cid->completed event and wait on it for some timeout * so that the app thinks is it running async. * * All async ServerSupportFunction calls will be handled through * the registered IO_COMPLETION hook. */ if (!isa->fakeasync) { 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->r->status = HTTP_INTERNAL_SERVER_ERROR; } } else { cid->complete = CreateEvent(NULL, FALSE, FALSE, NULL); if (WaitForSingleObject(cid->complete, isa->timeout) == WAIT_TIMEOUT) { /* TODO: Now what... if this hung, then do we kill our own * thread to force it's death? For now leave timeout = -1 */ } } break; case HSE_STATUS_ERROR: /* end response if we have yet to do so. */ cid->r->status = HTTP_INTERNAL_SERVER_ERROR; break; default: /* TODO: log unrecognized retval for debugging */ cid->r->status = HTTP_INTERNAL_SERVER_ERROR; break; } /* Set the status (for logging) */ if (cid->ecb->dwHttpStatusCode) { cid->r->status = cid->ecb->dwHttpStatusCode; } /* All done with the DLL... get rid of it... */ isapi_unload(isa, FALSE); return OK; /* NOT r->status, even if it has changed. */}#pragma optimize("",on)BOOL WINAPI GetServerVariable (HCONN hConn, LPSTR lpszVariableName, LPVOID lpvBuffer, LPDWORD lpdwSizeofBuffer){ request_rec *r = ((isapi_cid *)hConn)->r; const char *result; DWORD len; if (!strcmp(lpszVariableName, "ALL_HTTP")) { /* lf delimited, colon split, comma seperated and * null terminated list of HTTP_ vars */ char **env = (char**) apr_table_elts(r->subprocess_env)->elts; int nelts = 2 * apr_table_elts(r->subprocess_env)->nelts; int i; for (len = 0, i = 0; i < nelts; i += 2) if (!strncmp(env[i], "HTTP_", 5)) len += strlen(env[i]) + strlen(env[i + 1]) + 2; if (*lpdwSizeofBuffer < len + 1) { *lpdwSizeofBuffer = len + 1; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } for (i = 0; i < nelts; i += 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'; } *(((char*)lpvBuffer)++) = '\0'; *lpdwSizeofBuffer = len; return TRUE; } if (!strcmp(lpszVariableName, "ALL_RAW")) { /* lf delimited, colon split, comma seperated and * null terminated list of the raw request header */ char **raw = (char**) apr_table_elts(r->headers_in)->elts; int nelts = 2 * apr_table_elts(r->headers_in)->nelts; int i; for (len = 0, i = 0; i < nelts; i += 2) len += strlen(raw[i]) + strlen(raw[i + 1]) + 2; if (*lpdwSizeofBuffer < len + 1) { *lpdwSizeofBuffer = len + 1; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } for (i = 0; i < nelts; i += 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; } /* Not a special case */ result = apr_table_get(r->subprocess_env, lpszVariableName); if (result) { len = strlen(result); if (*lpdwSizeofBuffer < len + 1) { *lpdwSizeofBuffer = len + 1; SetLastError(ERROR_INSUFFICIENT_BUFFER); return FALSE; } strcpy(lpvBuffer, result); *lpdwSizeofBuffer = len; return TRUE; } /* Not Found */ SetLastError(ERROR_INVALID_INDEX); return FALSE;}BOOL WINAPI WriteClient (HCONN ConnID, LPVOID Buffer, LPDWORD lpwdwBytes, DWORD dwReserved)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -