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
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;
|
|
}
|