Annotation of parser3/src/targets/isapi/parser3isapi.C, revision 1.82.2.6.2.4
1.29 paf 1: /** @file
2: Parser: IIS extension.
3:
1.82.2.1 paf 4: Copyright (c) 2000,2001-2003 ArtLebedev Group (http://www.artlebedev.com)
1.63 paf 5: Author: Alexandr Petrosian <paf@design.ru> (http://paf.design.ru)
1.77 paf 6: */
1.29 paf 7:
1.82.2.6.2.4! paf 8: static const char* IDENT_PARSER3ISAPI_C="$Date: 2003/03/20 14:19:10 $";
1.29 paf 9:
1.1 paf 10: #ifndef _MSC_VER
1.10 paf 11: # error compile ISAPI module with MSVC [no urge for now to make it autoconf-ed (PAF)]
1.1 paf 12: #endif
1.43 parser 13:
14: #include "pa_config_includes.h"
1.1 paf 15:
1.9 paf 16: #include "pa_sapi.h"
1.1 paf 17: #include "pa_globals.h"
18: #include "pa_request.h"
19: #include "pa_version.h"
1.13 paf 20: #include "pool_storage.h"
1.24 paf 21: #include "pa_socks.h"
1.1 paf 22:
1.64 paf 23: #include <windows.h>
24: #include <process.h>
25:
26: #include <httpext.h>
1.51 parser 27:
1.1 paf 28: #define MAX_STATUS_LENGTH sizeof("xxxx LONGEST STATUS DESCRIPTION")
1.44 parser 29:
30: // consts
1.1 paf 31:
1.82.2.1 paf 32: const char* IIS51vars[]={
1.73 paf 33: "APPL_MD_PATH", "APPL_PHYSICAL_PATH",
34: "AUTH_PASSWORD", "AUTH_TYPE", "AUTH_USER",
35: "CERT_COOKIE", "CERT_FLAGS", "CERT_ISSUER", "CERT_KEYSIZE", "CERT_SECRETKEYSIZE",
36: "CERT_SERIALNUMBER", "CERT_SERVER_ISSUER", "CERT_SERVER_SUBJECT", "CERT_SUBJECT",
37: "CONTENT_LENGTH", "CONTENT_TYPE",
38: "LOGON_USER",
39: "HTTPS", "HTTPS_KEYSIZE", "HTTPS_SECRETKEYSIZE", "HTTPS_SERVER_ISSUER", "HTTPS_SERVER_SUBJECT",
40: "INSTANCE_ID", "INSTANCE_META_PATH",
41: "PATH_INFO", "PATH_TRANSLATED",
42: "QUERY_STRING",
43: "REMOTE_ADDR", "REMOTE_HOST", "REMOTE_USER", "REQUEST_METHOD",
44: "SCRIPT_NAME",
45: "SERVER_NAME", "SERVER_PORT", "SERVER_PORT_SECURE", "SERVER_PROTOCOL", "SERVER_SOFTWARE",
46: "URL",
47: };
48: const int IIS51var_count=sizeof(IIS51vars)/sizeof(*IIS51vars);
49:
1.65 paf 50: // globals
51:
52: char argv0[MAX_STRING]="";
53:
1.18 paf 54: // SAPI
55:
1.38 parser 56: #ifndef DOXYGEN
57: /*
1.18 paf 58: ISAPI SAPI functions receive this context information.
1.38 parser 59: see Pool::set_context
1.18 paf 60: */
1.15 paf 61: struct SAPI_func_context {
1.3 paf 62: LPEXTENSION_CONTROL_BLOCK lpECB;
63: String *header;
64: DWORD http_response_code;
65: };
1.38 parser 66: #endif
1.3 paf 67:
1.26 paf 68: // goes to 'cs-uri-query' log file field. webmaster: switch it ON[default OFF].
1.82.2.6.2.1 paf 69: void SAPI::logconst char* fmt, ...) {
1.53 parser 70: SAPI_func_context& ctx=*static_cast<SAPI_func_context *>(pool.get_context());
1.26 paf 71:
72: va_list args;
73: va_start(args,fmt);
74: char buf[MAX_STRING];
1.82.2.1 paf 75: const char* prefix="PARSER_ERROR:";
1.26 paf 76: strcpy(buf, prefix);
1.47 parser 77: char *start=buf+strlen(prefix);
1.51 parser 78: DWORD size=vsnprintf(start, MAX_STRING-strlen(prefix), fmt, args);
1.47 parser 79: remove_crlf(start, start+size);
80:
1.26 paf 81: ctx.lpECB->ServerSupportFunction(ctx.lpECB->ConnID,
82: HSE_APPEND_LOG_PARAMETER, buf, &size, 0);
1.55 parser 83: }
84:
85: /// @todo event log
1.82.2.6 paf 86: static void die_or_abort(const char* fmt, va_list args, bool write_core) {
87: if(FILE *log=fopen("c:\\parser3die.log", "at")) {
1.65 paf 88: vfprintf(log, fmt, args);
89: fclose(log);
90: }
1.81 paf 91: // exit & try to produce core dump
92: abort();
1.26 paf 93: }
1.82.2.6 paf 94: void SAPI::die(const char* fmt, ...) {
95: va_list args;
96: va_start(args, fmt);
97: die_or_abort(fmt, args, false/*write core?*/);
98: va_end(args);
99: }
100:
101: void SAPI::abort(const char* fmt, ...) {
102: va_list args;
103: va_start(args, fmt);
104: die_or_abort(fmt, args, true/*write core?*/);
105: va_end(args);
106: }
1.26 paf 107:
1.82.2.6.2.1 paf 108: const char* SAPI::get_envconst char* name) {
1.53 parser 109: SAPI_func_context& ctx=*static_cast<SAPI_func_context *>(pool.get_context());
1.1 paf 110:
1.82.2.6.2.1 paf 111: char *variable_buf=new char[MAX_STRING];
1.1 paf 112: DWORD variable_len = MAX_STRING-1;
113:
1.3 paf 114: if(ctx.lpECB->GetServerVariable(ctx.lpECB->ConnID, const_cast<char *>(name),
1.1 paf 115: variable_buf, &variable_len)) {
1.73 paf 116: if(*variable_buf) { // saw returning len=1 && *buf=0 :(
117: variable_buf[variable_len]=0;
118: return variable_buf;
119: }
1.7 paf 120: } else if (GetLastError()==ERROR_INSUFFICIENT_BUFFER) {
1.82.2.6.2.1 paf 121: variable_buf=new char[variable_len+1];
1.7 paf 122:
123: if(ctx.lpECB->GetServerVariable(ctx.lpECB->ConnID, const_cast<char *>(name),
124: variable_buf, &variable_len)) {
1.73 paf 125: if(*variable_buf) {
126: variable_buf[variable_len]=0;
127: return variable_buf;
128: }
1.7 paf 129: }
1.1 paf 130: }
1.7 paf 131:
1.1 paf 132: return 0;
133: }
134:
1.82.2.1 paf 135: static int grep_char(const char* s, char c) {
1.72 paf 136: int result=0;
137: if(s) {
138: while(s=strchr(s, c)) {
139: s++; // skip found c
140: result++;
141: }
142: }
143: return result;
144: }
1.82.2.6.2.1 paf 145: static const char* mk_env_pairconst char* key, const char* value) {
146: char *result=new char[strlen(key)+1/*=*/+strlen(value)+1/*0*/];
1.72 paf 147: strcpy(result, key); strcat(result, "="); strcat(result, value);
148: return result;
149: }
1.82.2.6.2.1 paf 150: const char* const *SAPI::environment(SAPI_Info& info, ) {
1.72 paf 151: // we know this buf is writable
1.82.2.6.2.2 paf 152: const char* all_http_vars=SAPI::get_env("ALL_HTTP");
1.72 paf 153: const int http_var_count=grep_char(all_http_vars, '\n')+1/*\n for theoretical(never saw) this \0*/;
154:
1.82.2.6.2.1 paf 155: const char* *result=new const char*[IIS51var_count+http_var_count+1/*0*/];
1.82.2.1 paf 156: const char* *cur=result;
1.72 paf 157:
158: // IIS5.1 vars
159: for(int i=0; i<IIS51var_count; i++) {
1.82.2.1 paf 160: const char* key=IIS51vars[i];
1.82.2.6.2.2 paf 161: if(const char* value=SAPI::get_env(key))
162: *cur++=mk_env_pair(key, value);
1.72 paf 163: }
164:
165: // HTTP_* vars
166: if(char *s=all_http_vars) {
167: while(char *key=lsplit(&s, '\n'))
168: if(char *value=lsplit(key, ':'))
1.82.2.6.2.2 paf 169: *cur++=mk_env_pair(key, value);
1.72 paf 170: }
171:
172: // mark EOE
173: *cur=0;
174:
175: return result;
176: }
177:
1.82.2.6.2.1 paf 178: size_t SAPI::read_postchar *buf, size_t max_bytes) {
1.53 parser 179: SAPI_func_context& ctx=*static_cast<SAPI_func_context *>(pool.get_context());
1.1 paf 180:
181: DWORD read_from_buf=0;
182: DWORD read_from_input=0;
183: DWORD total_read=0;
184:
1.3 paf 185: read_from_buf=min(ctx.lpECB->cbAvailable, max_bytes);
186: memcpy(buf, ctx.lpECB->lpbData, read_from_buf);
1.1 paf 187: total_read+=read_from_buf;
188:
189: if(read_from_buf<max_bytes &&
1.3 paf 190: read_from_buf<ctx.lpECB->cbTotalBytes) {
1.1 paf 191: DWORD cbRead=0, cbSize;
192:
1.3 paf 193: read_from_input=min(max_bytes-read_from_buf,
194: ctx.lpECB->cbTotalBytes-read_from_buf);
1.1 paf 195: while(cbRead < read_from_input) {
196: cbSize=read_from_input - cbRead;
1.3 paf 197: if(!ctx.lpECB->ReadClient(ctx.lpECB->ConnID,
198: buf+read_from_buf+cbRead, &cbSize) ||
1.1 paf 199: cbSize==0)
200: break;
201: cbRead+=cbSize;
202: }
203: total_read+=cbRead;
204: }
205: return total_read;
206: }
207:
1.82.2.6.2.1 paf 208: void SAPI::add_header_attribute
1.82.2.2 paf 209: const char* dont_store_key, const char* dont_store_value) {
1.53 parser 210: SAPI_func_context& ctx=*static_cast<SAPI_func_context *>(pool.get_context());
1.3 paf 211:
212: if(strcasecmp(key, "location")==0)
213: ctx.http_response_code=302;
214:
215: if(strcasecmp(key, "status")==0)
1.82.2.2 paf 216: ctx.http_response_code=atoi(dont_store_value);
1.3 paf 217: else {
1.82.2.2 paf 218: todo: copy dont_store_ to nonvilotile
219: ctx.header->APPEND_CONST(dont_store_key);
1.3 paf 220: ctx.header->APPEND_CONST(": ");
1.82.2.2 paf 221: ctx.header->APPEND_CONST(dont_store_value);
1.30 paf 222: ctx.header->APPEND_CONST("\r\n");
1.3 paf 223: }
1.1 paf 224: }
225:
1.23 paf 226: /// @todo intelligent cache-control
1.82.2.6.2.1 paf 227: void SAPI::send_header() {
1.53 parser 228: SAPI_func_context& ctx=*static_cast<SAPI_func_context *>(pool.get_context());
1.1 paf 229:
1.64 paf 230: HSE_SEND_HEADER_EX_INFO header_info;
1.1 paf 231:
232: char status_buf[MAX_STATUS_LENGTH];
1.3 paf 233: switch(ctx.http_response_code) {
1.1 paf 234: case 200:
235: header_info.pszStatus="200 OK";
236: break;
237: case 302:
238: header_info.pszStatus="302 Moved Temporarily";
239: break;
1.8 paf 240: case 401:// useless untill parser auth mech
1.1 paf 241: header_info.pszStatus="401 Authorization Required";
1.8 paf 242: break;
1.1 paf 243: default:
1.3 paf 244: snprintf(status_buf, MAX_STATUS_LENGTH,
245: "%d Undescribed", ctx.http_response_code);
1.1 paf 246: header_info.pszStatus=status_buf;
247: break;
248: }
249: header_info.cchStatus=strlen(header_info.pszStatus);
1.66 paf 250: *ctx.header << "\r\n"; // ISAPI v<5 did quite well without it
1.3 paf 251: header_info.pszHeader=ctx.header->cstr();
1.82.2.6.2.3 paf 252: header_info.cchHeader=ctx.header->length();
1.5 paf 253: header_info.fKeepConn=true;
1.1 paf 254:
1.3 paf 255: ctx.lpECB->dwHttpStatusCode=ctx.http_response_code;
1.1 paf 256:
1.3 paf 257: ctx.lpECB->ServerSupportFunction(ctx.lpECB->ConnID,
258: HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
1.1 paf 259: }
260:
1.82.2.6.2.1 paf 261: void SAPI::send_bodyconst void *buf, size_t size) {
1.53 parser 262: SAPI_func_context& ctx=*static_cast<SAPI_func_context *>(pool.get_context());
1.1 paf 263:
264: DWORD num_bytes=size;
1.3 paf 265: ctx.lpECB->WriteClient(ctx.lpECB->ConnID,
1.23 paf 266: const_cast<void *>(buf), &num_bytes, HSE_IO_SYNC);
1.1 paf 267: }
1.16 paf 268:
1.1 paf 269:
1.15 paf 270: static bool parser_init() {
1.1 paf 271: static bool globals_inited=false;
272: if(globals_inited)
1.15 paf 273: return true;
1.1 paf 274: globals_inited=true;
275:
1.65 paf 276: static Pool pool(&pool_storage); // global pool
1.53 parser 277: try {
1.27 paf 278: // init socks
1.82.2.6.2.1 paf 279: pa_init_socks();
1.32 paf 280: // init global classes
1.82.2.6.2.1 paf 281: init_methoded_array();
1.1 paf 282: // init global variables
1.82.2.6.2.1 paf 283: pa_globals_init();
1.65 paf 284:
1.15 paf 285: // successful finish
286: return true;
1.53 parser 287: } catch(const Exception& e) { // global problem
1.82.2.1 paf 288: const char* body=e.comment();
1.15 paf 289:
290: // unsuccessful finish
291: return false;
1.1 paf 292: }
293: }
294:
295: /// ISAPI //
296: BOOL WINAPI GetExtensionVersion(HSE_VERSION_INFO *pVer) {
297: pVer->dwExtensionVersion = HSE_VERSION;
1.36 parser 298: strncpy(pVer->lpszExtensionDesc, "Parser "PARSER_VERSION, HSE_MAX_EXT_DLL_NAME_LEN-1);
299: pVer->lpszExtensionDesc[HSE_MAX_EXT_DLL_NAME_LEN-1]=0;
1.15 paf 300: return parser_init();
1.1 paf 301: }
302:
1.6 paf 303: /**
304: ISAPI // main workhorse
305:
1.23 paf 306: @todo
1.10 paf 307: IIS: remove trailing default-document[index.html] from $request.uri.
308: to do that we need to consult metabase,
1.12 paf 309: wich is tested&works but seems slow runtime
310: and not could-be-quickly-implemented if prepared.
1.37 parser 311: @test
312: PARSER_VERSION from outside
1.6 paf 313: */
1.53 parser 314:
1.82.2.6.2.1 paf 315: void real_parser_handlerLPEXTENSION_CONTROL_BLOCK lpECB, bool header_only) {
316: static_cast<SAPI_func_context *>(pool.get_context())->header=new String();
1.53 parser 317:
318: // Request info
319: Request::Info request_info;
320:
321: size_t path_translated_buf_size=strlen(lpECB->lpszPathTranslated)+1;
1.82.2.4 paf 322: char *filespec_to_process=pool.copy(lpECB->lpszPathTranslated, path_translated_buf_size);
1.53 parser 323: #ifdef WIN32
324: back_slashes_to_slashes(filespec_to_process);
325: #endif
326:
1.82.2.6.2.2 paf 327: if(const char* path_info=SAPI::get_env("PATH_INFO")) {
1.53 parser 328: // IIS
329: size_t len=strlen(filespec_to_process)-strlen(path_info);
1.82.2.6.2.1 paf 330: char *buf=new char[len+1];
1.53 parser 331: strncpy(buf, filespec_to_process, len); buf[len]=0;
332: request_info.document_root=buf;
333: } else
1.67 paf 334: throw Exception("parser.runtime",
1.53 parser 335: 0,
336: "ISAPI: no PATH_INFO defined (in reinventing DOCUMENT_ROOT)");
337:
338: request_info.path_translated=filespec_to_process;
339: request_info.method=lpECB->lpszMethod;
340: request_info.query_string=lpECB->lpszQueryString;
341: if(lpECB->lpszQueryString && *lpECB->lpszQueryString) {
1.82.2.6.2.1 paf 342: char *reconstructed_uri=new char[
1.53 parser 343: strlen(lpECB->lpszPathInfo)+1/*'?'*/+
1.82.2.4 paf 344: strlen(lpECB->lpszQueryString)+1/*0*/];
1.53 parser 345: strcpy(reconstructed_uri, lpECB->lpszPathInfo);
346: strcat(reconstructed_uri, "?");
347: strcat(reconstructed_uri, lpECB->lpszQueryString);
348: request_info.uri=reconstructed_uri;
349: } else
350: request_info.uri=lpECB->lpszPathInfo;
351:
352: request_info.content_type=lpECB->lpszContentType;
353: request_info.content_length=lpECB->cbTotalBytes;
1.82.2.6.2.2 paf 354: request_info.cookie=SAPI::get_env("HTTP_COOKIE");
1.76 paf 355: request_info.mail_received=false;
1.53 parser 356:
357: // prepare to process request
358: Request request(pool,
359: request_info,
1.82.2.6.2.4! paf 360: String::L_HTML|String::L_OPTIMIZE_BIT,
1.70 paf 361: #ifdef _DEBUG
362: true
363: #else
364: false
365: #endif
366: /* status_allowed */);
1.53 parser 367:
1.65 paf 368: // beside by binary
1.75 paf 369: static char beside_binary_path[MAX_STRING];
370: strncpy(beside_binary_path, argv0, MAX_STRING-1); beside_binary_path[MAX_STRING-1]=0; // filespec of my binary
1.65 paf 371: if(!(
1.75 paf 372: rsplit(beside_binary_path, '/') ||
373: rsplit(beside_binary_path, '\\'))) { // strip filename
1.65 paf 374: // no path, just filename
1.75 paf 375: beside_binary_path[0]='.'; beside_binary_path[1]=0;
1.65 paf 376: }
1.74 paf 377: char config_filespec[MAX_STRING];
378: snprintf(config_filespec, MAX_STRING,
1.65 paf 379: "%s/%s",
1.75 paf 380: beside_binary_path, AUTO_FILE_NAME);
1.79 paf 381: bool fail_on_config_read_problem=entry_exists(config_filespec);
1.65 paf 382:
1.53 parser 383: // process the request
384: request.core(
1.79 paf 385: config_filespec, fail_on_config_read_problem, // /path/to/first/auto.p
1.53 parser 386: header_only);
387: }
388:
1.82.2.6.2.1 paf 389: void call_real_parser_handler__do_SEH
1.53 parser 390: LPEXTENSION_CONTROL_BLOCK lpECB,
391: bool header_only) {
1.54 parser 392: #if _MSC_VER & !defined(_DEBUG)
1.53 parser 393: LPEXCEPTION_POINTERS system_exception=0;
394: __try {
395: #endif
1.82.2.6.2.2 paf 396: real_parser_handler(lpECB, header_only);
1.53 parser 397:
1.54 parser 398: #if _MSC_VER & !defined(_DEBUG)
1.53 parser 399: } __except (
400: (system_exception=GetExceptionInformation()),
401: EXCEPTION_EXECUTE_HANDLER) {
402:
403: if(system_exception)
404: if(_EXCEPTION_RECORD *er=system_exception->ExceptionRecord)
1.67 paf 405: throw Exception(0,
1.53 parser 406: 0,
407: "Exception 0x%08X at 0x%08X", er->ExceptionCode, er->ExceptionAddress);
408: else
1.67 paf 409: throw Exception(0, 0, "Exception <no exception record>");
1.53 parser 410: else
1.67 paf 411: throw Exception(0, 0, "Exception <no exception information>");
1.53 parser 412: }
413: #endif
414: }
415:
1.71 paf 416: inline DWORD RealHttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) {
1.13 paf 417: Pool_storage pool_storage;
1.15 paf 418: Pool pool(&pool_storage); // no allocations until assigned context [for reporting]
419: SAPI_func_context ctx={
420: lpECB,
1.18 paf 421: 0, // filling later: so that if there would be error pool would have ctx
1.80 paf 422: 200 // default http_response_code [lpECB->dwHttpStatusCode seems to be always 0, even on 404 redirect to /404.html]
1.15 paf 423: };
424: pool.set_context(&ctx);// no allocations before this line!
1.71 paf 425:
1.1 paf 426: bool header_only=strcasecmp(lpECB->lpszMethod, "HEAD")==0;
1.53 parser 427: try { // global try
1.82.2.6.2.2 paf 428: call_real_parser_handler__do_SEH(lpECB, header_only);
1.2 paf 429: // successful finish
1.53 parser 430: } catch(const Exception& e) { // global problem
1.12 paf 431: // don't allocate anything on pool here:
432: // possible pool' exception not catch-ed now
1.31 paf 433: // and there could be out-of-memory exception
1.82.2.1 paf 434: const char* body=e.comment();
1.16 paf 435: // log it
1.82.2.6.2.2 paf 436: SAPI::log("exception in request exception handler: %s", body);
1.16 paf 437:
438: //
1.1 paf 439: int content_length=strlen(body);
440:
1.12 paf 441: // prepare header // not using SAPI func wich allocates on pool
442: char header_buf[MAX_STRING];
443: int header_len=snprintf(header_buf, MAX_STRING,
1.30 paf 444: "content-type: text/plain\r\n"
445: "content-length: %lu\r\n"
1.69 paf 446: // "expires: Fri, 23 Mar 2001 09:32:23 GMT\r\n"
1.30 paf 447: "\r\n",
1.12 paf 448: content_length);
449:
450: HSE_SEND_HEADER_EX_INFO header_info;
451: header_info.pszStatus="200 OK";
452: header_info.cchStatus=strlen(header_info.pszStatus);
453: header_info.pszHeader=header_buf;
454: header_info.cchHeader=header_len;
455: header_info.fKeepConn=true;
456:
1.1 paf 457: // send header
1.12 paf 458: lpECB->dwHttpStatusCode=200;
459: lpECB->ServerSupportFunction(lpECB->ConnID,
460: HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
1.1 paf 461:
462: // send body
463: if(!header_only)
1.82.2.6.2.2 paf 464: SAPI::send_body(body, content_length);
1.1 paf 465:
466: // unsuccessful finish
467: }
1.65 paf 468: /*
1.82.2.1 paf 469: const char* body="test";
1.65 paf 470:
471: //
472: int content_length=strlen(body);
473:
474: // prepare header // not using SAPI func wich allocates on pool
475: char header_buf[MAX_STRING];
476: int header_len=snprintf(header_buf, MAX_STRING,
477: "content-type: text/plain\r\n"
478: "content-length: %lu\r\n"
479: "expires: Fri, 23 Mar 2001 09:32:23 GMT\r\n"
480: "\r\n",
481: content_length);
482: HSE_SEND_HEADER_EX_INFO header_info;
483: header_info.pszStatus="200 OK";
484: header_info.cchStatus=strlen(header_info.pszStatus);
485: header_info.pszHeader=header_buf;
486: header_info.cchHeader=header_len;
487: header_info.fKeepConn=true;
488:
489: // send header
490: lpECB->dwHttpStatusCode=200;
491: lpECB->ServerSupportFunction(lpECB->ConnID,
492: HSE_REQ_SEND_RESPONSE_HEADER_EX, &header_info, NULL, NULL);
493:
494: // send body
495: DWORD num_bytes=content_length;
496: lpECB->WriteClient(lpECB->ConnID,
497: (void *)body, &num_bytes, HSE_IO_SYNC);
498: */
1.71 paf 499: return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
500: }
1.66 paf 501:
1.71 paf 502: #ifdef _DEBUG
503: //for memory leaks detection only
504: #undef _WINDOWS_
505: #include <afx.h>
506: #endif
507: DWORD WINAPI HttpExtensionProc(LPEXTENSION_CONTROL_BLOCK lpECB) {
508: // Declare the variables needed
509: #ifdef _DEBUG
510: // _crtBreakAlloc=97779;//97777; //997;
511:
512: CMemoryState oldMemState, newMemState, diffMemState;
513: oldMemState.Checkpoint();
514: //global_pool_storagep->fbreak_on_alloc=true;
515: #endif
516:
517: DWORD result=RealHttpExtensionProc(lpECB);
518:
519: #ifdef _DEBUG
520: newMemState.Checkpoint();
521: if( diffMemState.Difference( oldMemState, newMemState ) )
522: {
523: TRACE( "Memory leaked!\n" );
524: diffMemState.DumpStatistics( );
525: diffMemState.DumpAllObjectsSince();
526: }
527: #endif
528: return result;
1.1 paf 529: }
1.65 paf 530:
531: BOOL WINAPI DllMain(
532: HINSTANCE hinstDLL, // handle to the DLL module
533: DWORD fdwReason, // reason for calling function
534: LPVOID lpvReserved // reserved
535: ) {
536:
537: GetModuleFileName(
538: hinstDLL, // handle to module
539: argv0, // file name of module
540: sizeof(argv0) // size of buffer
541: );
542:
543: return TRUE;
544: }
E-mail: