398 lines
11 KiB
C++
398 lines
11 KiB
C++
/*++
|
|
|
|
Copyright (c) 1998 Microsoft Corporation
|
|
|
|
Module Name :
|
|
WpConfig.cxx
|
|
|
|
Abstract:
|
|
Module implementing the Worker Process Configuration Data structure.
|
|
WP_CONFIG object encapsulates configuration supplied from the commandline
|
|
as well as remotely supplied from the admin process.
|
|
|
|
Author:
|
|
|
|
Murali R. Krishnan ( MuraliK ) 21-Oct-1998
|
|
|
|
Environment:
|
|
Win32 - User Mode
|
|
|
|
Project:
|
|
IIS Worker Process
|
|
--*/
|
|
|
|
|
|
/************************************************************
|
|
* Include Headers
|
|
************************************************************/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
/*
|
|
Usage: \bin\iisrearc\inetsrv\iiswp [options] APN
|
|
APN -- AppPool Name
|
|
-d <URL List> -- Indicates that the process should register the given
|
|
namespace itself. This mode is for running worker process in
|
|
stand alone mode (for debugging)
|
|
-l -- Log errors that stop the worker process into the eventlog
|
|
-ld -- Disables logging the errors of worker process to eventlog
|
|
(default is not write to eventlog)
|
|
-a -- Look for web admin service and register with the same
|
|
(default is look for web admin service)
|
|
-ad -- Do not look for web admin service and do registration
|
|
-r <n> -- Restart the worker process after n requests.
|
|
-t <n> -- Shutdown the worker process if idle for n milliseconds.
|
|
<URL List> uses the syntax: {http[s]://IP:port/URL | http[s]://hostname:port/URL }+
|
|
with space as separator
|
|
eg: -d http://localhost:80/ => listen for all HTTP requests on port 80
|
|
eg: -d http://localhost:80/ http://localhost:81/ => listen on port 80 & 81
|
|
|
|
*/
|
|
|
|
const CHAR g_rgchUsage[] =
|
|
"Usage: %ws [options] APN\n"
|
|
"\tAPN -- AppPool Name\n"
|
|
"\t-d <URL List> -- Indicates that the process should register the given \n"
|
|
"\t\tnamespace itself. This mode is for running worker process in\n"
|
|
"\t\tstand alone mode (for debugging)\n"
|
|
"\t-l -- Log errors that stop the worker process into the eventlog\n"
|
|
"\t-ld -- Disables logging the errors of worker process to eventlog\n"
|
|
"\t\t(default is not write to eventlog)\n"
|
|
"\t-a -- Look for web admin service and register with the same\n"
|
|
"\t\t(default is look for web admin service)\n"
|
|
"\t-ad -- Do not look for web admin service and do registration\n"
|
|
"\t-r <n> -- Restart the worker process after n requests\n"
|
|
"\t-t <n> -- Shutdown the worker process if idle for n milliseconds\n"
|
|
"\t-p -- Tell COR to add IceCAP instrumentation\n"
|
|
"\t<URL List> uses the syntax: {http[s]://IP:port/URL | http[s]://hostname:port/URL }+\n"
|
|
"\t\twith space as separator\n"
|
|
"\t\t eg: -d http://*:80/ => listen for all HTTP requests on port 80\n"
|
|
"\t\t eg: -d http://localhost:80/ http://localhost:81/ => listen on port 80 & 81\n"
|
|
;
|
|
|
|
/************************************************************
|
|
* Member functions of WP_CONFIG
|
|
************************************************************/
|
|
|
|
WP_CONFIG::WP_CONFIG(void)
|
|
: _pwszAppPoolName (AP_NAME),
|
|
_fSetupControlChannel(false),
|
|
_fLogErrorsToEventLog(false),
|
|
_fRegisterWithWAS (true),
|
|
_RestartCount (0),
|
|
_NamedPipeId (0),
|
|
_IdleTime (0)
|
|
{
|
|
lstrcpy( _pwszProgram, L"WP");
|
|
}
|
|
|
|
WP_CONFIG::~WP_CONFIG()
|
|
{
|
|
_ulcc.Cleanup();
|
|
}
|
|
|
|
|
|
void
|
|
WP_CONFIG::PrintUsage() const
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, g_rgchUsage, _pwszProgram));
|
|
}
|
|
|
|
/********************************************************************++
|
|
|
|
Routine Description:
|
|
Parses the command line to read in all configuration supplied.
|
|
This function updates the state variables inside WP_CONFIG for use
|
|
in starting up the Worker process.
|
|
|
|
See g_rgchUsage[] for details on the arguments that can be supplied
|
|
|
|
Arguments:
|
|
argc - count of arguments supplied
|
|
argv - pointer to strings containing the arguments.
|
|
|
|
Returns:
|
|
Boolean
|
|
|
|
--********************************************************************/
|
|
BOOL
|
|
WP_CONFIG::ParseCommandLine(int argc, PWSTR argv[])
|
|
{
|
|
BOOL fRet = true;
|
|
int iArg;
|
|
|
|
lstrcpyn( _pwszProgram, argv[0], sizeof _pwszProgram / sizeof _pwszProgram[0]);
|
|
|
|
if ( argc < 2)
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Invalid number of parameters (%d)\n", argc));
|
|
PrintUsage();
|
|
return (false);
|
|
}
|
|
|
|
for( iArg = 1; iArg < argc; iArg++)
|
|
{
|
|
if ( (argv[iArg][0] == L'-') || (argv[iArg][0] == L'/'))
|
|
{
|
|
switch (argv[iArg][1])
|
|
{
|
|
|
|
case L'c': case L'C':
|
|
DBGPRINTF((DBG_CONTEXT, "-C: obsolete\n"));
|
|
break;
|
|
|
|
case L'd': case L'D':
|
|
|
|
_fSetupControlChannel = true;
|
|
iArg++;
|
|
|
|
while ( (iArg < argc-1) &&
|
|
(argv[iArg][0] != L'-') && (argv[iArg][0] != L'/'))
|
|
{
|
|
if ( !InsertURLIntoList(argv[iArg]) )
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Invalid URL: %ws\n", argv[iArg]));
|
|
}
|
|
|
|
iArg++;
|
|
}
|
|
|
|
iArg--;
|
|
break;
|
|
|
|
case L'a': case L'A':
|
|
if ( (L'd' == argv[iArg][2]) || (L'D' == argv[iArg][2]))
|
|
{
|
|
_fRegisterWithWAS = false;
|
|
}
|
|
else
|
|
{
|
|
// -a NamedPipeId
|
|
if (L'\0' == argv[iArg][2])
|
|
{
|
|
iArg++;
|
|
}
|
|
|
|
_NamedPipeId = wcstoul(argv[iArg], NULL, 0);
|
|
DBGPRINTF((DBG_CONTEXT, "NamedPipe Id, %lu\n", _NamedPipeId));
|
|
|
|
if (0 == _NamedPipeId)
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Invalid NamedPipe Id, %ws\n",
|
|
argv[iArg]));
|
|
fRet = false;
|
|
}
|
|
}
|
|
break;
|
|
|
|
case L'l': case L'L':
|
|
DBGPRINTF((DBG_CONTEXT, "Warning: This option is not supported presently\n"));
|
|
if (L' ' == argv[iArg][0])
|
|
{
|
|
_fLogErrorsToEventLog = true;
|
|
}
|
|
break;
|
|
|
|
case L'r': case L'R':
|
|
_RestartCount = wcstoul(argv[++iArg], NULL, 0);
|
|
|
|
if (_RestartCount == 0)
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Invalid maximum requests %ws\n", argv[iArg]));
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Maximum requests is %lu\n", _RestartCount));
|
|
}
|
|
break;
|
|
|
|
case L't': case L'T':
|
|
_IdleTime = wcstoul(argv[++iArg], NULL, 0);
|
|
|
|
if (_IdleTime == 0)
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "Invalid idle time %ws\n", argv[iArg]));
|
|
return false;
|
|
}
|
|
else
|
|
{
|
|
DBGPRINTF((DBG_CONTEXT, "The idle time value is %lu\n", _IdleTime));
|
|
}
|
|
break;
|
|
|
|
case L'p': case L'P':
|
|
SetEnvironmentVariable(L"CORDBG_ENABLE", L"0x20");
|
|
SetEnvironmentVariable(L"COR_PROFILER", L"\"ComPlusIcecapProfile.CorIcecapProfiler\"");
|
|
SetEnvironmentVariable(L"PROF_CONFIG", L"/callcap");
|
|
|
|
break;
|
|
|
|
default:
|
|
case L'?':
|
|
fRet = false;
|
|
break;
|
|
} // switch
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Take the next item as the NSG name and bail out here
|
|
//
|
|
_pwszAppPoolName = argv[iArg];
|
|
|
|
if ( iArg != (argc - 1))
|
|
{
|
|
//
|
|
// this is not the last argument => unwanted parameters exist
|
|
// give warning and ignore
|
|
//
|
|
DBGPRINTF((DBG_CONTEXT, "Warning: Too many arguments supplied\n"));
|
|
}
|
|
|
|
break; // get out of here.
|
|
}
|
|
}
|
|
|
|
if (!_fRegisterWithWAS)
|
|
{
|
|
_RestartCount = 0;
|
|
_IdleTime = 0;
|
|
}
|
|
|
|
if (!fRet)
|
|
{
|
|
PrintUsage();
|
|
}
|
|
|
|
return ( fRet);
|
|
|
|
} // WP_CONFIG::ParseCommandLine()
|
|
|
|
|
|
/********************************************************************++
|
|
|
|
Routine Description:
|
|
Sets up the control channel for processing requests. It uses
|
|
the configuration parameters supplied for initializing the
|
|
UL_CONTROL_CHANNEL.
|
|
|
|
See g_rgchUsage[] for details on the arguments that can be supplied
|
|
|
|
Arguments:
|
|
|
|
Returns:
|
|
Win32 error
|
|
|
|
--********************************************************************/
|
|
|
|
ULONG
|
|
WP_CONFIG::SetupControlChannel(void)
|
|
{
|
|
|
|
//
|
|
// Setup a control channel for our local use now. Used mainly for
|
|
// the purpose of debugging.
|
|
// In general control channel work is done by the AdminProces.
|
|
//
|
|
|
|
return _ulcc.Initialize( _mszURLList, _pwszAppPoolName);
|
|
|
|
} // WP_CONFIG::SetupControlChannel()
|
|
|
|
/********************************************************************++
|
|
--********************************************************************/
|
|
|
|
WP_CONFIG::InsertURLIntoList( LPCWSTR pwszURL )
|
|
{
|
|
LPCWSTR pwszOriginalURL = pwszURL;
|
|
|
|
//
|
|
// Minimum length: 11 (http://*:1/). Begins with http
|
|
//
|
|
|
|
if ( ( wcslen(pwszURL) < 11 ) || ( 0 != _wcsnicmp(pwszURL, L"http", 4)) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
pwszURL += 4;
|
|
|
|
//
|
|
// https
|
|
//
|
|
|
|
if ((L's' == *pwszURL) || (L'S' == *pwszURL))
|
|
{
|
|
pwszURL++;
|
|
}
|
|
|
|
//
|
|
// ://
|
|
//
|
|
|
|
if ( (L':' != *pwszURL) || (L'/' != *(pwszURL+1)) || (L'/' != *(pwszURL+2)) )
|
|
{
|
|
return false;
|
|
}
|
|
|
|
pwszURL += 3;
|
|
|
|
//
|
|
// Skip host name or Ip Address
|
|
//
|
|
|
|
while ( (0 != *pwszURL) && ( L':' != *pwszURL))
|
|
{
|
|
pwszURL++;
|
|
}
|
|
|
|
//
|
|
// Check port # exists
|
|
//
|
|
|
|
if (0 == *pwszURL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// Check port number is numeric
|
|
//
|
|
|
|
pwszURL++;
|
|
|
|
while ( (0 != *pwszURL) && ( L'/' != *pwszURL) )
|
|
{
|
|
if (( L'0' > *pwszURL) || ( L'9' < *pwszURL))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
pwszURL++;
|
|
}
|
|
|
|
//
|
|
// Check / after port number exists
|
|
//
|
|
|
|
if (0 == *pwszURL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//
|
|
// URL is good.
|
|
//
|
|
|
|
IF_DEBUG( TRACE)
|
|
{
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Inserting URL '%ws' into Config Group List\n",
|
|
pwszOriginalURL
|
|
));
|
|
}
|
|
return ( TRUE == _mszURLList.Append( pwszOriginalURL));
|
|
|
|
} // WP_CONFIG::InsertURLIntoList()
|