Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

760 lines
22 KiB

/*++
Copyright (c) 1994 Microsoft Corporation
Module Name:
w3test.c
Abstract:
This module tests the web server's server extension interface
Author:
John Ludeman (johnl) 13-Oct-1994
Revision History:
Tony Godfrey (tonygod) 15-Sep-1997 - fixed TerminateExtension
--*/
#include <windows.h>
//#include <httpext.h>
#include <iisext.h>
// Global variable used to track outstanding threads
DWORD g_dwThreadCount;
#define BUFFER_LENGTH 4096
// Debug macro
CHAR g_szDebug[256];
#define DEBUG(DebugString, Param)\
{\
wsprintf( g_szDebug, DebugString, Param );\
OutputDebugString( g_szDebug );\
}
// Prototypes
DWORD WINAPI SimulatePendIOThread( LPDWORD lpParams );
BOOL WINAPI DllMain( HANDLE hInst, ULONG Reason, LPVOID Reserved );
BOOL WINAPI DoAction(
EXTENSION_CONTROL_BLOCK * pecb,
char * pszAction,
BOOL * pfKeepConn
);
DWORD WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK * pecb )
{
BOOL fKeepConn = FALSE;
DWORD dwThreadId;
HANDLE hThread;
if ( !_strnicmp( pecb->lpszQueryString,
"SimulatePendingIO",
17))
{
InterlockedIncrement( &g_dwThreadCount );
hThread = CreateThread(
NULL,
0,
(LPTHREAD_START_ROUTINE) SimulatePendIOThread,
pecb,
0,
&dwThreadId
);
if ( hThread == NULL ) {
InterlockedDecrement( &g_dwThreadCount );
} else {
CloseHandle( hThread );
}
return HSE_STATUS_PENDING;
}
else
{
if ( !DoAction( pecb,
pecb->lpszQueryString,
&fKeepConn ))
{
return HSE_STATUS_ERROR;
}
}
return fKeepConn ? HSE_STATUS_SUCCESS_AND_KEEP_CONN :
HSE_STATUS_SUCCESS;
}
BOOL WINAPI DoAction(
EXTENSION_CONTROL_BLOCK * pecb,
char * pszAction,
BOOL * pfKeepConn
)
{
char *buff;
int ret;
int i;
int cb;
buff = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, BUFFER_LENGTH + 1 );
if ( buff == NULL ) {
return FALSE;
}
//
// Log the request here
//
strcpy( pecb->lpszLogData, ", ISAPI Data->" );
strcat( pecb->lpszLogData, pszAction );
if ( !_stricmp( pszAction,
"HSE_REQ_SEND_URL_REDIRECT_RESP" ))
{
//
// pecb->pszPathInfo is the URL to redirect to
//
HeapFree( GetProcessHeap(), 0, buff );
return pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_URL_REDIRECT_RESP,
pecb->lpszPathInfo,
NULL,
NULL );
}
else if ( !_stricmp( pszAction,
"HSE_REQ_SEND_URL" ))
{
//
// pecbb->lpszPathInfo is the URL to send
//
HeapFree( GetProcessHeap(), 0, buff );
return pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_URL,
pecb->lpszPathInfo,
0,
0 );
}
else if ( !_stricmp( pszAction,
"HSE_REQ_SEND_RESPONSE_HEADER" ))
{
wsprintf( buff,
"Content-type: text/html\r\n"
"\r\n"
"<head><title>Response header test</title></head>\n"
"<body><h1>HTTP status code supplied in the path info was \"%s\"</h1></body>\n",
pecb->lpszPathInfo );
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
pecb->lpszPathInfo, // HTTP status code
NULL,
(LPDWORD) buff );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
cb = wsprintf( buff,
"Content-Type: text/html\r\n"
"\r\n"
"<head><title>Response header test</title></head>\n"
"<body><h1>Specified status code was %s</h1></body>\n",
pecb->lpszPathInfo );
ret = pecb->WriteClient( pecb->ConnID,
buff,
&cb,
0 );
HeapFree( GetProcessHeap(), 0, buff );
return ret;
}
else if ( !_strnicmp( pszAction,
"GET_VAR",
7 ))
{
CHAR * pch;
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
NULL,
NULL,
(LPDWORD) "Content-Type: text/html\r\n"
"\r\n" );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
cb = BUFFER_LENGTH;
if ( !(pch = strchr( pszAction, '&' )) )
{
pch = "ALL_HTTP";
}
else
{
pch++;
}
ret = pecb->GetServerVariable( pecb->ConnID,
pch,
buff,
&cb );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
strcat( buff, "\r\n" );
cb = strlen( buff );
ret = pecb->WriteClient( pecb->ConnID,
buff,
&cb,
0 );
HeapFree( GetProcessHeap(), 0, buff );
return ret;
}
else if ( !_stricmp( pszAction,
"HSE_REQ_MAP_URL_TO_PATH" ))
{
char Path[MAX_PATH + 1];
DWORD cbPath = sizeof( Path );
strcpy( Path, pecb->lpszPathInfo );
ret = pecb->ServerSupportFunction( pecb->ConnID,
HSE_REQ_MAP_URL_TO_PATH,
Path,
&cbPath,
NULL );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
wsprintf( buff,
"Content-type: text/html\r\n"
"\r\n"
"<head><title>URL map test</title></head>\n"
"<body><h1>URL \"%s\" maps to \"%s\""
"cbPath is %d</h1></body>\n",
pecb->lpszPathInfo,
Path,
cbPath );
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
NULL,
NULL,
(LPDWORD) buff );
HeapFree( GetProcessHeap(), 0, buff );
return ret;
}
else if ( !_stricmp( pszAction,
"HSE_REQ_MAP_URL_TO_PATH_EX" ))
{
HSE_URL_MAPEX_INFO mapinfo;
ret = pecb->ServerSupportFunction( pecb->ConnID,
HSE_REQ_MAP_URL_TO_PATH_EX,
pecb->lpszPathInfo,
NULL,
(DWORD *) &mapinfo );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
wsprintf( buff,
"Content-type: text/html\r\n"
"\r\n"
"<head><title>URL map_ex test</title></head>\n"
"<body><h1>URL \"%s\" maps to \"%s\""
"dwFlags = 0x%08x\n"
"cchMatchingPath = %d\n"
"cchMatchingURL = %d\n</h1></body>",
pecb->lpszPathInfo,
mapinfo.lpszPath,
mapinfo.dwFlags,
mapinfo.cchMatchingPath,
mapinfo.cchMatchingURL );
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
NULL,
NULL,
(LPDWORD) buff );
HeapFree( GetProcessHeap(), 0, buff );
return ret;
}
else if ( !_stricmp( pszAction,
"Keep_Alive" ))
{
DWORD cbBuff = BUFFER_LENGTH;
DWORD cbDoc;
CHAR achDoc[4096];
BOOL fKeepAlive = FALSE;
if ( !pecb->GetServerVariable( pecb->ConnID,
"HTTP_CONNECTION",
buff,
&cbBuff ))
{
*buff = '\0';
}
cbDoc = wsprintf( achDoc,
"<head><title>Keep alive test</title></head>\n"
"This document is being kept alive."
);
//
// This assumes keep-alive comes first in the list
//
if ( !_strnicmp( buff, "keep-alive", 10 ))
{
fKeepAlive = TRUE;
wsprintf( buff,
"Content-type: text/html\r\n"
"Connection: keep-alive\r\n"
"Content-Length: %d\r\n"
"\r\n",
cbDoc );
}
else
{
wsprintf( buff,
"Content-type: text/html\r\n"
"\r\n"
"<head><title>Keep alive test</title></head>\n"
"Client did not specify keep alive!"
);
}
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
NULL,
NULL,
(LPDWORD) buff ) &&
pecb->WriteClient( pecb->ConnID,
achDoc,
&cbDoc,
0 );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
if ( fKeepAlive ) {
*pfKeepConn = TRUE;
}
HeapFree( GetProcessHeap(), 0, buff );
return TRUE;
}
else if ( !strncmp( pszAction,
"Open_Reg",
7 ))
{
CHAR * pch;
DWORD err;
HKEY hKey;
HKEY hSubKey;
HANDLE hFile;
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
NULL,
NULL,
(LPDWORD) "Content-Type: text/html\r\n"
"\r\n" );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
//
// The path info begins with the portion of the registry to open
//
if ( !_strnicmp( pecb->lpszPathInfo + 1,
"HKEY_CLASSES_ROOT",
17 ))
{
pch = pecb->lpszPathInfo + 19;
hKey = HKEY_CLASSES_ROOT;
}
else if ( !_strnicmp( pecb->lpszPathInfo + 1,
"HKEY_CURRENT_USER",
17 ))
{
pch = pecb->lpszPathInfo + 19;
hKey = HKEY_CURRENT_USER;
}
else if ( !_strnicmp( pecb->lpszPathInfo + 1,
"HKEY_LOCAL_MACHINE",
18 ))
{
pch = pecb->lpszPathInfo + 20;
hKey = HKEY_LOCAL_MACHINE;
}
else if ( !_strnicmp( pecb->lpszPathInfo + 1,
"HKEY_USERS",
10 ))
{
pch = pecb->lpszPathInfo + 12;
hKey = HKEY_USERS;
}
err = RegOpenKey( hKey,
pch,
&hSubKey );
if ( err )
{
cb = wsprintf( buff,
"Failed to open registry key %s, error %d\n",
pecb->lpszPathInfo,
err );
}
else
{
cb = wsprintf( buff,
"Successfully opened registry key %s\n",
pecb->lpszPathInfo );
RegCloseKey( hSubKey );
}
pecb->WriteClient( pecb->ConnID,
buff,
&cb,
0 );
HeapFree( GetProcessHeap(), 0, buff );
return TRUE;
}
else if ( !_stricmp( pszAction,
"Open_File" ))
{
CHAR *pch;
DWORD err;
HKEY hKey;
HKEY hSubKey;
HANDLE hFile;
DWORD dwBytesRead;
DWORD dwFileSize = 0;
DWORD dwError;
//
// The path translated is the filename to open
//
hFile = CreateFile(
pecb->lpszPathTranslated,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL,
NULL
);
if ( hFile == INVALID_HANDLE_VALUE ) {
dwError = GetLastError();
wsprintf(
buff,
"Content-Type: text/html\r\n\r\n"
);
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
"200 OK",
NULL,
(LPDWORD) buff );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
cb = wsprintf(
buff,
"<head><title>Unable to open file</title></head>\r\n"
"<body><h1>Unable to open file</h1>\r\n"
"CreateFile failed: %ld\r\n<p>"
"Filename: %s<p></body>",
dwError,
pecb->lpszPathTranslated
);
pecb->WriteClient(
pecb->ConnID,
buff,
&cb,
0
);
HeapFree( GetProcessHeap(), 0, buff );
return TRUE;
}
dwFileSize = GetFileSize( hFile, NULL );
pch = HeapAlloc( GetProcessHeap(), HEAP_ZERO_MEMORY, dwFileSize + 1 );
ret = ReadFile(
hFile,
pch,
dwFileSize,
&dwBytesRead,
NULL
);
if ( !ret ) {
dwError = GetLastError();
}
pch[dwBytesRead] = 0;
CloseHandle( hFile );
if ( !ret ) {
wsprintf(
buff,
"Content-Type: text/html\r\n\r\n"
);
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
"200 OK",
NULL,
(LPDWORD) buff );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
cb = wsprintf(
buff,
"<head><title>Unable to Read File</title></head>\r\n"
"<body><h1>Unable to Read File</h1>\r\n"
"ReadFile failed: %ld<p>\r\n"
"Filename: %s</body>",
dwError,
pecb->lpszPathTranslated
);
pecb->WriteClient(
pecb->ConnID,
buff,
&cb,
0
);
HeapFree( GetProcessHeap(), 0, buff );
return TRUE;
}
wsprintf(
buff,
"Content-Type: text/html\r\n\r\n"
);
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
"200 OK",
NULL,
(LPDWORD) buff );
if ( !ret ) {
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
pecb->WriteClient(
pecb->ConnID,
pch,
&dwBytesRead,
0
);
HeapFree( GetProcessHeap(), 0, buff );
HeapFree( GetProcessHeap(), 0, pch );
return TRUE;
}
else if ( !_stricmp( pszAction,
"SimulateFault" ))
{
*((CHAR *)0xffffffff) = 'a';
HeapFree( GetProcessHeap(), 0, buff );
return FALSE;
}
wsprintf( buff,
"Content-Type: text/html\r\n\r\n"
"<head><title>Unknown Test command</title></head>\n"
"<body><h1>Unknown Test Command</h1>\n"
"<p>Usage:"
"<p>Query string contains one of the following:"
"<p>"
"<p> HSE_REQ_SEND_URL_REDIRECT_RESP"
"<p> HSE_REQ_SEND_URL"
"<p> HSE_REQ_SEND_RESPONSE_HEADER"
"<p> HSE_REQ_MAP_URL_TO_PATH"
"<p> GET_VAR&var_to_get"
"<p> SimulateFault"
"<p> Keep_Alive"
"<p> Open_Reg"
"<p> Open_File"
"<p>"
"<p> For example:"
"<p>"
"<p> http://computer/scripts/w3test.dll?CGI_VAR"
"<p>"
"<p> or SimulatePendingIO with one of the above action strings"
"<p>"
"<p> such as:"
"<p>"
"<p> http://computer/scripts/w3test.dll?SimulatePendingIO&HSE_REQ_SEND_URL"
"<p>"
"<p> The Path info generally contains the URL or response to use"
"</body>\n");
ret = pecb->ServerSupportFunction(
pecb->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER,
"200 OK",
NULL,
(LPDWORD) buff );
cb = wsprintf( buff,
"<p>cbTotalBytes = %d<p> cbAvailable = %d<p>"
"lpszContentType = %s<p> lpszPathInfo = %s<p>"
"lpszPathTranslated = %s",
pecb->cbTotalBytes,
pecb->cbAvailable,
pecb->lpszContentType,
pecb->lpszPathInfo,
pecb->lpszPathTranslated );
pecb->WriteClient( pecb->ConnID,
buff,
&cb,
0 );
cb = pecb->cbAvailable;
pecb->WriteClient( pecb->ConnID,
pecb->lpbData,
&cb,
0 );
while ( pecb->cbAvailable < pecb->cbTotalBytes )
{
cb = min( pecb->cbTotalBytes - pecb->cbAvailable, BUFFER_LENGTH );
if ( !pecb->ReadClient( pecb->ConnID,
buff,
&cb ) ||
!cb )
{
break;
}
pecb->cbAvailable += cb;
pecb->WriteClient( pecb->ConnID,
buff,
&cb,
0 );
}
HeapFree( GetProcessHeap(), 0, buff );
return TRUE;
}
DWORD WINAPI SimulatePendIOThread( LPDWORD lpParams )
{
EXTENSION_CONTROL_BLOCK * pecb = (EXTENSION_CONTROL_BLOCK *) lpParams;
char *psz;
DWORD dwStatus;
BOOL fKeepConn = FALSE;
Sleep( 5000 );
psz = strchr( pecb->lpszQueryString, '&' );
if ( psz )
psz++;
else
psz = "No action string specified";
DoAction( pecb,
psz,
&fKeepConn );
dwStatus = fKeepConn ? HSE_STATUS_SUCCESS_AND_KEEP_CONN :
HSE_STATUS_SUCCESS;
pecb->ServerSupportFunction( pecb,
HSE_REQ_DONE_WITH_SESSION,
&dwStatus,
0,
0 );
InterlockedDecrement( &g_dwThreadCount );
return 0;
}
BOOL GetExtensionVersion( HSE_VERSION_INFO * pver )
{
pver->dwExtensionVersion = MAKELONG( 0, 1 );
strcpy( pver->lpszExtensionDesc, "Extension test example" );
return TRUE;
}
BOOL TerminateExtension( DWORD dwFlags )
{
DEBUG( "[W3Test.TerminateExtension] Extension terminating!\r\n", 0 );
while ( g_dwThreadCount > 0 ) {
DEBUG( "[W3Test.TerminateExtension] Thread Count: %ld\r\n", g_dwThreadCount );
SleepEx( 1000, FALSE );
}
SleepEx( 1000, FALSE );
return TRUE;
}
BOOL WINAPI DllMain( HANDLE hInst, ULONG Reason, LPVOID Reserved )
{
switch( Reason ) {
case DLL_PROCESS_ATTACH:
g_dwThreadCount = 0;
break;
case DLL_PROCESS_DETACH:
break;
}
return TRUE;
}