388 lines
8.7 KiB
C
388 lines
8.7 KiB
C
/*++
|
||
|
||
Copyright (c) 2000 Microsoft Corporation
|
||
|
||
Module Name:
|
||
|
||
tfilt.c
|
||
|
||
Abstract:
|
||
|
||
Stupid filter test server for UL.SYS.
|
||
This program configures a global filter called TestFilter
|
||
and then servs requests like tfile. See tupfilt and tsslfilt
|
||
for actual filter processes.
|
||
|
||
Author:
|
||
|
||
Michael Courage (mcourage) 16-Mar-2000
|
||
|
||
Revision History:
|
||
|
||
--*/
|
||
|
||
|
||
#include "precomp.h"
|
||
|
||
|
||
DEFINE_COMMON_GLOBALS();
|
||
|
||
|
||
ULONG
|
||
InitFilterStuff(
|
||
IN HANDLE ControlChannel,
|
||
OUT PHANDLE pFitlerHandle
|
||
);
|
||
|
||
|
||
INT
|
||
__cdecl
|
||
wmain(
|
||
INT argc,
|
||
PWSTR argv[]
|
||
)
|
||
{
|
||
ULONG result;
|
||
HANDLE controlChannel;
|
||
HANDLE appPool;
|
||
HANDLE filterChannel;
|
||
HTTP_CONFIG_GROUP_ID configId;
|
||
HTTP_CONFIG_GROUP_APP_POOL configAppPool;
|
||
HTTP_CONFIG_GROUP_STATE configState;
|
||
HTTP_ENABLED_STATE controlState;
|
||
HTTP_REQUEST_ID requestId;
|
||
DWORD bytesRead;
|
||
DWORD bytesSent;
|
||
PHTTP_REQUEST request;
|
||
HTTP_RESPONSE response;
|
||
HTTP_DATA_CHUNK dataChunk;
|
||
PWSTR fileNamePart;
|
||
ULONG i;
|
||
ULONG urlLength;
|
||
PWSTR url;
|
||
PWSTR tmp;
|
||
BOOL initDone;
|
||
HTTP_REQUEST_ALIGNMENT UCHAR requestBuffer[REQUEST_LENGTH];
|
||
WCHAR fileName[MAX_PATH + 10];
|
||
|
||
//
|
||
// Initialize.
|
||
//
|
||
|
||
result = CommonInit();
|
||
|
||
if (result != NO_ERROR)
|
||
{
|
||
wprintf( L"CommonInit() failed, error %lu\n", result );
|
||
return 1;
|
||
}
|
||
|
||
if (!ParseCommandLine( argc, argv ))
|
||
{
|
||
return 1;
|
||
}
|
||
|
||
//
|
||
// Setup locals so we know how to cleanup on exit.
|
||
//
|
||
|
||
initDone = FALSE;
|
||
controlChannel = NULL;
|
||
appPool = NULL;
|
||
filterChannel = NULL;
|
||
HTTP_SET_NULL_ID( &configId );
|
||
|
||
//
|
||
// Get UL started.
|
||
//
|
||
|
||
result = InitUlStuff(
|
||
&controlChannel,
|
||
&appPool,
|
||
&filterChannel, // FilterChannel
|
||
&configId,
|
||
TRUE, // AllowSystem
|
||
TRUE, // AllowAdmin
|
||
FALSE, // AllowCurrentUser
|
||
FALSE, // AllowWorld
|
||
0,
|
||
TRUE, // EnableSsl
|
||
TRUE // EnableRawFilters
|
||
);
|
||
|
||
if (result != NO_ERROR)
|
||
{
|
||
wprintf( L"InitUlStuff() failed, error %lu\n", result );
|
||
goto cleanup;
|
||
}
|
||
/*
|
||
result = InitFilterStuff(
|
||
controlChannel,
|
||
&filterChannel
|
||
);
|
||
|
||
if (result != NO_ERROR)
|
||
{
|
||
wprintf( L"InitFilterStuff() failed, error %lu\n", result );
|
||
goto cleanup;
|
||
}
|
||
*/
|
||
initDone = TRUE;
|
||
|
||
//
|
||
// Get the local directory and build part of the fully canonicalized
|
||
// NT path. This makes it a bit faster to build the physical file name
|
||
// down in the request/response loop.
|
||
//
|
||
|
||
GetCurrentDirectoryW( MAX_PATH, fileName );
|
||
|
||
if (fileName[wcslen(fileName) - 1] == L'\\' )
|
||
{
|
||
fileName[wcslen(fileName) - 1] = L'\0';
|
||
}
|
||
|
||
fileNamePart = fileName + wcslen(fileName);
|
||
|
||
//
|
||
// Build the fixed part of our response.
|
||
//
|
||
|
||
INIT_RESPONSE( &response, 200, "OK" );
|
||
|
||
//
|
||
// Loop forever...
|
||
//
|
||
|
||
request = (PHTTP_REQUEST)requestBuffer;
|
||
|
||
HTTP_SET_NULL_ID( &requestId );
|
||
|
||
for( ; ; )
|
||
{
|
||
//
|
||
// Wait for a request.
|
||
//
|
||
|
||
//DEBUG_BREAK();
|
||
result = HttpReceiveHttpRequest(
|
||
appPool,
|
||
requestId,
|
||
0,
|
||
(PHTTP_REQUEST)requestBuffer,
|
||
sizeof(requestBuffer),
|
||
&bytesRead,
|
||
NULL
|
||
);
|
||
|
||
if (result != NO_ERROR)
|
||
{
|
||
wprintf( L"HttpReceiveHttpRequest() failed, error %lu\n", result );
|
||
break;
|
||
}
|
||
|
||
//
|
||
// Dump it.
|
||
//
|
||
|
||
if (TEST_OPTION(Verbose))
|
||
{
|
||
DumpHttpRequest( request );
|
||
}
|
||
|
||
//
|
||
// Build the response.
|
||
//
|
||
|
||
url = request->CookedUrl.pFullUrl;
|
||
urlLength = request->CookedUrl.FullUrlLength;
|
||
|
||
//
|
||
// Hack: Find the port number, then skip to the following slash.
|
||
//
|
||
|
||
tmp = wcschr( url, L':' );
|
||
|
||
if (tmp != NULL)
|
||
{
|
||
tmp = wcschr( tmp, L'/' );
|
||
}
|
||
|
||
if (tmp != NULL)
|
||
{
|
||
tmp = wcschr( tmp, L':' );
|
||
}
|
||
|
||
if (tmp != NULL)
|
||
{
|
||
tmp = wcschr( tmp, L'/' );
|
||
}
|
||
|
||
if (tmp != NULL)
|
||
{
|
||
urlLength -= (ULONG)( (tmp - url) * sizeof(WCHAR) );
|
||
url = tmp;
|
||
}
|
||
|
||
//
|
||
// Map it into the filename.
|
||
//
|
||
|
||
for (i = 0 ; i < (urlLength/sizeof(WCHAR)) ; url++, i++)
|
||
{
|
||
if (*url == L'/')
|
||
{
|
||
fileNamePart[i] = L'\\';
|
||
}
|
||
else
|
||
{
|
||
fileNamePart[i] = *url;
|
||
}
|
||
}
|
||
|
||
fileNamePart[i] = L'\0';
|
||
|
||
if (wcscmp( fileNamePart, L"\\" ) == 0 )
|
||
{
|
||
wcscat( fileNamePart, L"default.htm" );
|
||
}
|
||
|
||
if (TEST_OPTION(Verbose))
|
||
{
|
||
wprintf(
|
||
L"mapped URL %s to physical file %s\n",
|
||
request->CookedUrl.pFullUrl,
|
||
fileName
|
||
);
|
||
}
|
||
|
||
dataChunk.DataChunkType = HttpDataChunkFromFileName;
|
||
dataChunk.FromFileName.FileNameLength = wcslen(fileName) * sizeof(WCHAR);
|
||
dataChunk.FromFileName.pFileName = fileName;
|
||
dataChunk.FromFileName.ByteRange.StartingOffset.QuadPart = 0;
|
||
dataChunk.FromFileName.ByteRange.Length.QuadPart = HTTP_BYTE_RANGE_TO_EOF;
|
||
|
||
//
|
||
// Send the canned response.
|
||
//
|
||
|
||
DEBUG_BREAK();
|
||
|
||
response.EntityChunkCount = 1;
|
||
response.pEntityChunks = &dataChunk;
|
||
|
||
result = HttpSendHttpResponse(
|
||
appPool,
|
||
request->RequestId,
|
||
0,
|
||
&response,
|
||
NULL,
|
||
&bytesSent,
|
||
NULL,
|
||
NULL
|
||
);
|
||
|
||
if ((result != NO_ERROR) && (result != ERROR_NETNAME_DELETED))
|
||
{
|
||
wprintf( L"HttpSendHttpResponse() failed, error %lu\n", result );
|
||
break;
|
||
}
|
||
}
|
||
|
||
cleanup:
|
||
|
||
if (!HTTP_IS_NULL_ID( &configId ))
|
||
{
|
||
result = HttpDeleteConfigGroup(
|
||
controlChannel,
|
||
configId
|
||
);
|
||
|
||
if (result != NO_ERROR)
|
||
{
|
||
wprintf( L"HttpDeleteConfigGroup() failed, error %lu\n", result );
|
||
}
|
||
}
|
||
|
||
if (filterChannel != NULL)
|
||
{
|
||
CloseHandle( filterChannel );
|
||
}
|
||
|
||
if (appPool != NULL)
|
||
{
|
||
CloseHandle( appPool );
|
||
}
|
||
|
||
if (controlChannel != NULL)
|
||
{
|
||
CloseHandle( controlChannel );
|
||
}
|
||
|
||
if (initDone)
|
||
{
|
||
HttpTerminate();
|
||
}
|
||
|
||
return 0;
|
||
|
||
} // wmain
|
||
|
||
|
||
ULONG
|
||
InitFilterStuff(
|
||
IN HANDLE ControlChannel,
|
||
OUT PHANDLE pFilterHandle
|
||
)
|
||
{
|
||
HANDLE filterHandle;
|
||
ULONG result;
|
||
HTTP_CONTROL_CHANNEL_FILTER controlFilter;
|
||
|
||
//
|
||
// Create the filter.
|
||
//
|
||
result = HttpCreateFilter(
|
||
&filterHandle, // filter handle
|
||
L"TestFilter", // filter name
|
||
NULL, // security attributes
|
||
HTTP_OPTION_OVERLAPPED // options
|
||
);
|
||
|
||
if (result == NO_ERROR)
|
||
{
|
||
//
|
||
// Attach the filter to the control channel.
|
||
//
|
||
RtlZeroMemory(&controlFilter, sizeof(controlFilter));
|
||
|
||
controlFilter.Flags.Present = 1;
|
||
controlFilter.FilterHandle = filterHandle;
|
||
controlFilter.FilterOnlySsl = FALSE;
|
||
|
||
result = HttpSetControlChannelInformation(
|
||
ControlChannel,
|
||
HttpControlChannelFilterInformation,
|
||
&controlFilter,
|
||
sizeof(controlFilter)
|
||
);
|
||
|
||
if (result == NO_ERROR)
|
||
{
|
||
//
|
||
// Return the filter handle.
|
||
//
|
||
*pFilterHandle = filterHandle;
|
||
}
|
||
else
|
||
{
|
||
CloseHandle(filterHandle);
|
||
}
|
||
}
|
||
|
||
return result;
|
||
}
|
||
|
||
|
||
|