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.
2514 lines
64 KiB
2514 lines
64 KiB
/*++
|
|
|
|
Copyright (c) 2000 Microsoft Corporation
|
|
|
|
Module Name :
|
|
servervar.cxx
|
|
|
|
Abstract:
|
|
Server Variable evaluation goo
|
|
|
|
Author:
|
|
Bilal Alam (balam) 20-Feb-2000
|
|
|
|
Environment:
|
|
Win32 - User Mode
|
|
|
|
Project:
|
|
ULW3.DLL
|
|
--*/
|
|
|
|
#include "precomp.hxx"
|
|
|
|
const DWORD MAX_IP_ADDRESS_CHARS = 15;
|
|
|
|
HRESULT
|
|
TranslateIpAddressToStr (
|
|
DWORD dwAddress,
|
|
STRA * pstraBuffer
|
|
)
|
|
/*++
|
|
Routine Description:
|
|
|
|
Convert DWORD representing IP address into a string in dotted format.
|
|
based in inet_ntoa. TLS has been eliminated adding a little perf gain.
|
|
|
|
Arguments:
|
|
|
|
dwAddress - DWORD address is in reverse order
|
|
pstraBuffer - static buffer containing the text address in standard ".''
|
|
notation.
|
|
|
|
Returns:
|
|
|
|
HRESULT
|
|
|
|
|
|
--*/
|
|
{
|
|
|
|
PUCHAR pAddress;
|
|
PUCHAR pCurrentChar;
|
|
HRESULT hr = E_FAIL;
|
|
STACK_STRA( strBuff, 32 );
|
|
static BYTE NToACharStrings[][4] = {
|
|
'0', 'x', 'x', 1,
|
|
'1', 'x', 'x', 1,
|
|
'2', 'x', 'x', 1,
|
|
'3', 'x', 'x', 1,
|
|
'4', 'x', 'x', 1,
|
|
'5', 'x', 'x', 1,
|
|
'6', 'x', 'x', 1,
|
|
'7', 'x', 'x', 1,
|
|
'8', 'x', 'x', 1,
|
|
'9', 'x', 'x', 1,
|
|
'1', '0', 'x', 2,
|
|
'1', '1', 'x', 2,
|
|
'1', '2', 'x', 2,
|
|
'1', '3', 'x', 2,
|
|
'1', '4', 'x', 2,
|
|
'1', '5', 'x', 2,
|
|
'1', '6', 'x', 2,
|
|
'1', '7', 'x', 2,
|
|
'1', '8', 'x', 2,
|
|
'1', '9', 'x', 2,
|
|
'2', '0', 'x', 2,
|
|
'2', '1', 'x', 2,
|
|
'2', '2', 'x', 2,
|
|
'2', '3', 'x', 2,
|
|
'2', '4', 'x', 2,
|
|
'2', '5', 'x', 2,
|
|
'2', '6', 'x', 2,
|
|
'2', '7', 'x', 2,
|
|
'2', '8', 'x', 2,
|
|
'2', '9', 'x', 2,
|
|
'3', '0', 'x', 2,
|
|
'3', '1', 'x', 2,
|
|
'3', '2', 'x', 2,
|
|
'3', '3', 'x', 2,
|
|
'3', '4', 'x', 2,
|
|
'3', '5', 'x', 2,
|
|
'3', '6', 'x', 2,
|
|
'3', '7', 'x', 2,
|
|
'3', '8', 'x', 2,
|
|
'3', '9', 'x', 2,
|
|
'4', '0', 'x', 2,
|
|
'4', '1', 'x', 2,
|
|
'4', '2', 'x', 2,
|
|
'4', '3', 'x', 2,
|
|
'4', '4', 'x', 2,
|
|
'4', '5', 'x', 2,
|
|
'4', '6', 'x', 2,
|
|
'4', '7', 'x', 2,
|
|
'4', '8', 'x', 2,
|
|
'4', '9', 'x', 2,
|
|
'5', '0', 'x', 2,
|
|
'5', '1', 'x', 2,
|
|
'5', '2', 'x', 2,
|
|
'5', '3', 'x', 2,
|
|
'5', '4', 'x', 2,
|
|
'5', '5', 'x', 2,
|
|
'5', '6', 'x', 2,
|
|
'5', '7', 'x', 2,
|
|
'5', '8', 'x', 2,
|
|
'5', '9', 'x', 2,
|
|
'6', '0', 'x', 2,
|
|
'6', '1', 'x', 2,
|
|
'6', '2', 'x', 2,
|
|
'6', '3', 'x', 2,
|
|
'6', '4', 'x', 2,
|
|
'6', '5', 'x', 2,
|
|
'6', '6', 'x', 2,
|
|
'6', '7', 'x', 2,
|
|
'6', '8', 'x', 2,
|
|
'6', '9', 'x', 2,
|
|
'7', '0', 'x', 2,
|
|
'7', '1', 'x', 2,
|
|
'7', '2', 'x', 2,
|
|
'7', '3', 'x', 2,
|
|
'7', '4', 'x', 2,
|
|
'7', '5', 'x', 2,
|
|
'7', '6', 'x', 2,
|
|
'7', '7', 'x', 2,
|
|
'7', '8', 'x', 2,
|
|
'7', '9', 'x', 2,
|
|
'8', '0', 'x', 2,
|
|
'8', '1', 'x', 2,
|
|
'8', '2', 'x', 2,
|
|
'8', '3', 'x', 2,
|
|
'8', '4', 'x', 2,
|
|
'8', '5', 'x', 2,
|
|
'8', '6', 'x', 2,
|
|
'8', '7', 'x', 2,
|
|
'8', '8', 'x', 2,
|
|
'8', '9', 'x', 2,
|
|
'9', '0', 'x', 2,
|
|
'9', '1', 'x', 2,
|
|
'9', '2', 'x', 2,
|
|
'9', '3', 'x', 2,
|
|
'9', '4', 'x', 2,
|
|
'9', '5', 'x', 2,
|
|
'9', '6', 'x', 2,
|
|
'9', '7', 'x', 2,
|
|
'9', '8', 'x', 2,
|
|
'9', '9', 'x', 2,
|
|
'1', '0', '0', 3,
|
|
'1', '0', '1', 3,
|
|
'1', '0', '2', 3,
|
|
'1', '0', '3', 3,
|
|
'1', '0', '4', 3,
|
|
'1', '0', '5', 3,
|
|
'1', '0', '6', 3,
|
|
'1', '0', '7', 3,
|
|
'1', '0', '8', 3,
|
|
'1', '0', '9', 3,
|
|
'1', '1', '0', 3,
|
|
'1', '1', '1', 3,
|
|
'1', '1', '2', 3,
|
|
'1', '1', '3', 3,
|
|
'1', '1', '4', 3,
|
|
'1', '1', '5', 3,
|
|
'1', '1', '6', 3,
|
|
'1', '1', '7', 3,
|
|
'1', '1', '8', 3,
|
|
'1', '1', '9', 3,
|
|
'1', '2', '0', 3,
|
|
'1', '2', '1', 3,
|
|
'1', '2', '2', 3,
|
|
'1', '2', '3', 3,
|
|
'1', '2', '4', 3,
|
|
'1', '2', '5', 3,
|
|
'1', '2', '6', 3,
|
|
'1', '2', '7', 3,
|
|
'1', '2', '8', 3,
|
|
'1', '2', '9', 3,
|
|
'1', '3', '0', 3,
|
|
'1', '3', '1', 3,
|
|
'1', '3', '2', 3,
|
|
'1', '3', '3', 3,
|
|
'1', '3', '4', 3,
|
|
'1', '3', '5', 3,
|
|
'1', '3', '6', 3,
|
|
'1', '3', '7', 3,
|
|
'1', '3', '8', 3,
|
|
'1', '3', '9', 3,
|
|
'1', '4', '0', 3,
|
|
'1', '4', '1', 3,
|
|
'1', '4', '2', 3,
|
|
'1', '4', '3', 3,
|
|
'1', '4', '4', 3,
|
|
'1', '4', '5', 3,
|
|
'1', '4', '6', 3,
|
|
'1', '4', '7', 3,
|
|
'1', '4', '8', 3,
|
|
'1', '4', '9', 3,
|
|
'1', '5', '0', 3,
|
|
'1', '5', '1', 3,
|
|
'1', '5', '2', 3,
|
|
'1', '5', '3', 3,
|
|
'1', '5', '4', 3,
|
|
'1', '5', '5', 3,
|
|
'1', '5', '6', 3,
|
|
'1', '5', '7', 3,
|
|
'1', '5', '8', 3,
|
|
'1', '5', '9', 3,
|
|
'1', '6', '0', 3,
|
|
'1', '6', '1', 3,
|
|
'1', '6', '2', 3,
|
|
'1', '6', '3', 3,
|
|
'1', '6', '4', 3,
|
|
'1', '6', '5', 3,
|
|
'1', '6', '6', 3,
|
|
'1', '6', '7', 3,
|
|
'1', '6', '8', 3,
|
|
'1', '6', '9', 3,
|
|
'1', '7', '0', 3,
|
|
'1', '7', '1', 3,
|
|
'1', '7', '2', 3,
|
|
'1', '7', '3', 3,
|
|
'1', '7', '4', 3,
|
|
'1', '7', '5', 3,
|
|
'1', '7', '6', 3,
|
|
'1', '7', '7', 3,
|
|
'1', '7', '8', 3,
|
|
'1', '7', '9', 3,
|
|
'1', '8', '0', 3,
|
|
'1', '8', '1', 3,
|
|
'1', '8', '2', 3,
|
|
'1', '8', '3', 3,
|
|
'1', '8', '4', 3,
|
|
'1', '8', '5', 3,
|
|
'1', '8', '6', 3,
|
|
'1', '8', '7', 3,
|
|
'1', '8', '8', 3,
|
|
'1', '8', '9', 3,
|
|
'1', '9', '0', 3,
|
|
'1', '9', '1', 3,
|
|
'1', '9', '2', 3,
|
|
'1', '9', '3', 3,
|
|
'1', '9', '4', 3,
|
|
'1', '9', '5', 3,
|
|
'1', '9', '6', 3,
|
|
'1', '9', '7', 3,
|
|
'1', '9', '8', 3,
|
|
'1', '9', '9', 3,
|
|
'2', '0', '0', 3,
|
|
'2', '0', '1', 3,
|
|
'2', '0', '2', 3,
|
|
'2', '0', '3', 3,
|
|
'2', '0', '4', 3,
|
|
'2', '0', '5', 3,
|
|
'2', '0', '6', 3,
|
|
'2', '0', '7', 3,
|
|
'2', '0', '8', 3,
|
|
'2', '0', '9', 3,
|
|
'2', '1', '0', 3,
|
|
'2', '1', '1', 3,
|
|
'2', '1', '2', 3,
|
|
'2', '1', '3', 3,
|
|
'2', '1', '4', 3,
|
|
'2', '1', '5', 3,
|
|
'2', '1', '6', 3,
|
|
'2', '1', '7', 3,
|
|
'2', '1', '8', 3,
|
|
'2', '1', '9', 3,
|
|
'2', '2', '0', 3,
|
|
'2', '2', '1', 3,
|
|
'2', '2', '2', 3,
|
|
'2', '2', '3', 3,
|
|
'2', '2', '4', 3,
|
|
'2', '2', '5', 3,
|
|
'2', '2', '6', 3,
|
|
'2', '2', '7', 3,
|
|
'2', '2', '8', 3,
|
|
'2', '2', '9', 3,
|
|
'2', '3', '0', 3,
|
|
'2', '3', '1', 3,
|
|
'2', '3', '2', 3,
|
|
'2', '3', '3', 3,
|
|
'2', '3', '4', 3,
|
|
'2', '3', '5', 3,
|
|
'2', '3', '6', 3,
|
|
'2', '3', '7', 3,
|
|
'2', '3', '8', 3,
|
|
'2', '3', '9', 3,
|
|
'2', '4', '0', 3,
|
|
'2', '4', '1', 3,
|
|
'2', '4', '2', 3,
|
|
'2', '4', '3', 3,
|
|
'2', '4', '4', 3,
|
|
'2', '4', '5', 3,
|
|
'2', '4', '6', 3,
|
|
'2', '4', '7', 3,
|
|
'2', '4', '8', 3,
|
|
'2', '4', '9', 3,
|
|
'2', '5', '0', 3,
|
|
'2', '5', '1', 3,
|
|
'2', '5', '2', 3,
|
|
'2', '5', '3', 3,
|
|
'2', '5', '4', 3,
|
|
'2', '5', '5', 3
|
|
};
|
|
|
|
|
|
hr = strBuff.Resize( MAX_IP_ADDRESS_CHARS + 1 ); // to assure buffer is big enough
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
PUCHAR pszBuffer = (PUCHAR) strBuff.QueryStr();
|
|
|
|
pCurrentChar = pszBuffer;
|
|
|
|
//
|
|
// In an unrolled loop, calculate the string value for each of the four
|
|
// bytes in an IP address. Note that for values less than 100 we will
|
|
// do one or two extra assignments, but we save a test/jump with this
|
|
// algorithm.
|
|
//
|
|
|
|
pAddress = (PUCHAR)&dwAddress;
|
|
//
|
|
// address is in reverse order
|
|
//
|
|
pAddress += 3;
|
|
|
|
*pCurrentChar = NToACharStrings[*pAddress][0];
|
|
*(pCurrentChar+1) = NToACharStrings[*pAddress][1];
|
|
*(pCurrentChar+2) = NToACharStrings[*pAddress][2];
|
|
pCurrentChar += NToACharStrings[*pAddress][3];
|
|
*pCurrentChar++ = '.';
|
|
|
|
pAddress--;
|
|
*pCurrentChar = NToACharStrings[*pAddress][0];
|
|
*(pCurrentChar+1) = NToACharStrings[*pAddress][1];
|
|
*(pCurrentChar+2) = NToACharStrings[*pAddress][2];
|
|
pCurrentChar += NToACharStrings[*pAddress][3];
|
|
*pCurrentChar++ = '.';
|
|
|
|
pAddress--;
|
|
*pCurrentChar = NToACharStrings[*pAddress][0];
|
|
*(pCurrentChar+1) = NToACharStrings[*pAddress][1];
|
|
*(pCurrentChar+2) = NToACharStrings[*pAddress][2];
|
|
pCurrentChar += NToACharStrings[*pAddress][3];
|
|
*pCurrentChar++ = '.';
|
|
|
|
pAddress--;
|
|
*pCurrentChar = NToACharStrings[*pAddress][0];
|
|
*(pCurrentChar+1) = NToACharStrings[*pAddress][1];
|
|
*(pCurrentChar+2) = NToACharStrings[*pAddress][2];
|
|
pCurrentChar += NToACharStrings[*pAddress][3];
|
|
*pCurrentChar = '\0';
|
|
|
|
return pstraBuffer->Copy( (CHAR*) pszBuffer );
|
|
}
|
|
|
|
|
|
//
|
|
// Hash table mapping variable name to a PFN_SERVER_VARIABLE_ROUTINE
|
|
//
|
|
|
|
|
|
SERVER_VARIABLE_HASH * SERVER_VARIABLE_HASH::sm_pRequestHash;
|
|
|
|
SERVER_VARIABLE_RECORD SERVER_VARIABLE_HASH::sm_rgServerRoutines[] =
|
|
{
|
|
{ "ALL_HTTP", GetServerVariableAllHttp, NULL, NULL },
|
|
{ "ALL_RAW", GetServerVariableAllRaw, NULL, NULL },
|
|
{ "APPL_MD_PATH", GetServerVariableApplMdPath, GetServerVariableApplMdPathW, NULL },
|
|
{ "APPL_PHYSICAL_PATH", GetServerVariableApplPhysicalPath, GetServerVariableApplPhysicalPathW , NULL },
|
|
{ "APP_POOL_ID", GetServerVariableAppPoolId, GetServerVariableAppPoolIdW, NULL },
|
|
{ "AUTH_PASSWORD", GetServerVariableAuthPassword, NULL, NULL },
|
|
{ "AUTH_TYPE", GetServerVariableAuthType, NULL, NULL },
|
|
{ "AUTH_USER", GetServerVariableRemoteUser, GetServerVariableRemoteUserW, NULL },
|
|
{ "CACHE_URL", GetServerVariableOriginalUrl, GetServerVariableOriginalUrlW, NULL },
|
|
{ "CERT_COOKIE", GetServerVariableClientCertCookie, NULL, NULL },
|
|
{ "CERT_FLAGS", GetServerVariableClientCertFlags, NULL, NULL },
|
|
{ "CERT_ISSUER", GetServerVariableClientCertIssuer, NULL, NULL },
|
|
{ "CERT_KEYSIZE", GetServerVariableHttpsKeySize, NULL, NULL },
|
|
{ "CERT_SECRETKEYSIZE", GetServerVariableHttpsSecretKeySize, NULL, NULL },
|
|
{ "CERT_SERIALNUMBER", GetServerVariableClientCertSerialNumber, NULL, NULL },
|
|
{ "CERT_SERVER_ISSUER", GetServerVariableHttpsServerIssuer, NULL, NULL },
|
|
{ "CERT_SERVER_SUBJECT", GetServerVariableHttpsServerSubject, NULL, NULL },
|
|
{ "CERT_SUBJECT", GetServerVariableClientCertSubject, NULL, NULL },
|
|
{ "CONTENT_LENGTH", GetServerVariableContentLength, NULL, NULL },
|
|
{ "CONTENT_TYPE", GetServerVariableContentType, NULL, NULL },
|
|
{ "GATEWAY_INTERFACE", GetServerVariableGatewayInterface, NULL, NULL },
|
|
{ "HTTPS", GetServerVariableHttps, NULL, NULL },
|
|
{ "HTTPS_KEYSIZE", GetServerVariableHttpsKeySize, NULL, NULL },
|
|
{ "HTTPS_SECRETKEYSIZE", GetServerVariableHttpsSecretKeySize, NULL, NULL },
|
|
{ "HTTPS_SERVER_ISSUER", GetServerVariableHttpsServerIssuer, NULL, NULL },
|
|
{ "HTTPS_SERVER_SUBJECT", GetServerVariableHttpsServerSubject, NULL, NULL },
|
|
{ "HTTP_URL", GetServerVariableHttpUrl, NULL, NULL },
|
|
{ "HTTP_METHOD", GetServerVariableRequestMethod, NULL, NULL },
|
|
{ "HTTP_VERSION", GetServerVariableHttpVersion, NULL, NULL },
|
|
{ "INSTANCE_ID", GetServerVariableInstanceId, NULL, NULL },
|
|
{ "INSTANCE_META_PATH", GetServerVariableInstanceMetaPath, NULL, NULL },
|
|
{ "LOCAL_ADDR", GetServerVariableLocalAddr, NULL, NULL },
|
|
{ "LOGON_USER", GetServerVariableLogonUser, GetServerVariableLogonUserW, NULL },
|
|
{ "PATH_INFO", GetServerVariablePathInfo, GetServerVariablePathInfoW, NULL },
|
|
{ "PATH_TRANSLATED", GetServerVariablePathTranslated, GetServerVariablePathTranslatedW, NULL },
|
|
{ "QUERY_STRING", GetServerVariableQueryString, NULL, NULL },
|
|
{ "REMOTE_ADDR", GetServerVariableRemoteAddr, NULL, NULL },
|
|
{ "REMOTE_HOST", GetServerVariableRemoteHost, NULL, NULL },
|
|
{ "REMOTE_PORT", GetServerVariableRemotePort, NULL, NULL },
|
|
{ "REMOTE_USER", GetServerVariableRemoteUser, GetServerVariableRemoteUserW, NULL },
|
|
{ "REQUEST_METHOD", GetServerVariableRequestMethod, NULL, NULL },
|
|
{ "SCRIPT_NAME", GetServerVariableUrl, GetServerVariableUrlW, NULL },
|
|
{ "SCRIPT_TRANSLATED", GetServerVariableScriptTranslated, GetServerVariableScriptTranslatedW, NULL },
|
|
{ "SERVER_NAME", GetServerVariableServerName, GetServerVariableServerNameW, NULL },
|
|
{ "SERVER_PORT", GetServerVariableServerPort, NULL, NULL },
|
|
{ "SERVER_PORT_SECURE", GetServerVariableServerPortSecure, NULL, NULL },
|
|
{ "SERVER_PROTOCOL", GetServerVariableHttpVersion, NULL, NULL },
|
|
{ "SERVER_SOFTWARE", GetServerVariableServerSoftware, NULL, NULL },
|
|
{ "SSI_EXEC_DISABLED", GetServerVariableSsiExecDisabled, NULL, NULL },
|
|
{ "UNENCODED_URL", GetServerVariableUnencodedUrl, NULL, NULL },
|
|
{ "UNMAPPED_REMOTE_USER", GetServerVariableRemoteUser, GetServerVariableRemoteUserW, NULL },
|
|
{ "URL", GetServerVariableUrl, GetServerVariableUrlW, NULL },
|
|
{ NULL, NULL, NULL, NULL }
|
|
};
|
|
|
|
//static
|
|
HRESULT
|
|
SERVER_VARIABLE_HASH::Initialize(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Initialize global server variable hash table
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
SERVER_VARIABLE_RECORD * pRecord;
|
|
LK_RETCODE lkrc = LK_SUCCESS;
|
|
|
|
sm_pRequestHash = new SERVER_VARIABLE_HASH;
|
|
if ( sm_pRequestHash == NULL )
|
|
{
|
|
return HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
|
|
}
|
|
|
|
//
|
|
// Add every string->routine mapping
|
|
//
|
|
|
|
pRecord = sm_rgServerRoutines;
|
|
while ( pRecord->_pszName != NULL )
|
|
{
|
|
sm_pRequestHash->InsertRecord( pRecord );
|
|
pRecord++;
|
|
}
|
|
|
|
//
|
|
// If any insert failed, then fail initialization
|
|
//
|
|
|
|
if ( lkrc != LK_SUCCESS )
|
|
{
|
|
delete sm_pRequestHash;
|
|
sm_pRequestHash = NULL;
|
|
return HRESULT_FROM_WIN32( lkrc ); // ARGH
|
|
}
|
|
else
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
//static
|
|
VOID
|
|
SERVER_VARIABLE_HASH::Terminate(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Cleanup global server variable hash table
|
|
|
|
Arguments:
|
|
|
|
None
|
|
|
|
Return Value:
|
|
|
|
None
|
|
|
|
--*/
|
|
{
|
|
if ( sm_pRequestHash != NULL )
|
|
{
|
|
delete sm_pRequestHash;
|
|
sm_pRequestHash = NULL;
|
|
}
|
|
}
|
|
|
|
//static
|
|
HRESULT
|
|
SERVER_VARIABLE_HASH::GetServerVariableRoutine(
|
|
CHAR * pszName,
|
|
PFN_SERVER_VARIABLE_ROUTINE * ppfnRoutine,
|
|
PFN_SERVER_VARIABLE_ROUTINE_W * ppfnRoutineW
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Lookup the hash table for a routine to evaluate the given variable
|
|
|
|
Arguments:
|
|
|
|
pszName - Name of server variable
|
|
ppfnRoutine - Set to the routine if successful
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
SERVER_VARIABLE_RECORD* pServerVariableRecord = NULL;
|
|
|
|
if ( pszName == NULL ||
|
|
ppfnRoutine == NULL ||
|
|
ppfnRoutineW == NULL )
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
|
|
}
|
|
|
|
DBG_ASSERT( sm_pRequestHash != NULL );
|
|
|
|
pServerVariableRecord = sm_pRequestHash->FindKey( pszName );
|
|
if ( pServerVariableRecord == NULL )
|
|
{
|
|
return HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT( pServerVariableRecord != NULL );
|
|
|
|
*ppfnRoutine = pServerVariableRecord->_pfnRoutine;
|
|
*ppfnRoutineW = pServerVariableRecord->_pfnRoutineW;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
|
|
//static
|
|
HRESULT
|
|
SERVER_VARIABLE_HASH::GetServerVariable(
|
|
W3_CONTEXT * pW3Context,
|
|
CHAR * pszVariableName,
|
|
CHAR * pszBuffer,
|
|
DWORD * pcbBuffer
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get server variable
|
|
|
|
Arguments:
|
|
|
|
pW3Context - W3_CONTEXT with request state. Can be NULL if we are
|
|
just determining whether the server variable requested is
|
|
valid.
|
|
pszVariable - Variable name to retrieve
|
|
pszBuffer - Filled with variable on success
|
|
pcbBuffer - On input, the size of input buffer. On out, the required size
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr;
|
|
DWORD cbOriginalBuffer = *pcbBuffer;
|
|
|
|
//
|
|
// For performance sake, do some Kung Fu to minimize buffer copies
|
|
// We'll initialize our string with the user's input buffer. If
|
|
// it wasn't big enough, we'll handle it
|
|
//
|
|
|
|
if (pszVariableName[0] == 'U' &&
|
|
strncmp(pszVariableName, "UNICODE_", 8) == 0)
|
|
{
|
|
WCHAR achBuffer[ 512 ];
|
|
STRU strValW( *pcbBuffer ? (LPWSTR)pszBuffer : achBuffer,
|
|
*pcbBuffer ? *pcbBuffer : sizeof( achBuffer ) );
|
|
|
|
hr = GetServerVariableW( pW3Context,
|
|
pszVariableName + 8,
|
|
&strValW );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
*pcbBuffer = strValW.QueryCB() + sizeof( WCHAR );
|
|
|
|
//
|
|
// Did we have to resize the buffer?
|
|
//
|
|
|
|
if ( strValW.QueryStr() != (LPWSTR) pszBuffer )
|
|
{
|
|
//
|
|
// Still might have enough space in source buffer, if
|
|
// ServerVariable routine resizes buffer to larger than
|
|
// really needed (lame)
|
|
//
|
|
|
|
if ( *pcbBuffer <= cbOriginalBuffer )
|
|
{
|
|
memcpy( pszBuffer,
|
|
strValW.QueryStr(),
|
|
*pcbBuffer );
|
|
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// User string wasn't big enough
|
|
//
|
|
|
|
return HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
CHAR achBuffer[ 512 ];
|
|
STRA strVal( *pcbBuffer ? pszBuffer : achBuffer,
|
|
*pcbBuffer ? *pcbBuffer : sizeof( achBuffer ) );
|
|
|
|
hr = GetServerVariable( pW3Context,
|
|
pszVariableName,
|
|
&strVal );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
*pcbBuffer = strVal.QueryCB() + sizeof( CHAR );
|
|
|
|
//
|
|
// Did we have to resize the buffer?
|
|
//
|
|
|
|
if ( strVal.QueryStr() != pszBuffer )
|
|
{
|
|
//
|
|
// Still might have enough space in source buffer, if
|
|
// ServerVariable routine resizes buffer to larger than
|
|
// really needed (lame)
|
|
//
|
|
|
|
if ( *pcbBuffer <= cbOriginalBuffer )
|
|
{
|
|
memcpy( pszBuffer,
|
|
strVal.QueryStr(),
|
|
*pcbBuffer );
|
|
|
|
return NO_ERROR;
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// User string wasn't big enough
|
|
//
|
|
|
|
return HRESULT_FROM_WIN32( ERROR_INSUFFICIENT_BUFFER );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return NO_ERROR;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
//static
|
|
HRESULT
|
|
SERVER_VARIABLE_HASH::GetServerVariable(
|
|
W3_CONTEXT * pW3Context,
|
|
CHAR * pszVariableName,
|
|
STRA * pstrVal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get server variable
|
|
|
|
Arguments:
|
|
|
|
pW3Context - W3_CONTEXT with request state. Can be NULL if we are
|
|
just determining whether the server variable requested is
|
|
valid. If NULL, we will return an empty string (and success)
|
|
if the variable requested is valid.
|
|
pszVariable - Variable name to retrieve
|
|
pstrVal - Filled with variable on success
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PFN_SERVER_VARIABLE_ROUTINE pfnRoutine = NULL;
|
|
PFN_SERVER_VARIABLE_ROUTINE_W pfnRoutineW = NULL;
|
|
|
|
//
|
|
// First: Is this a server variable we know about? If so handle it
|
|
// by calling the appropriate server variable routine
|
|
//
|
|
|
|
hr = SERVER_VARIABLE_HASH::GetServerVariableRoutine( pszVariableName,
|
|
&pfnRoutine,
|
|
&pfnRoutineW );
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
DBG_ASSERT( pfnRoutine != NULL );
|
|
|
|
if ( pW3Context != NULL )
|
|
{
|
|
return pfnRoutine( pW3Context, pstrVal );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// Just return empty string to signify that the variable is
|
|
// valid but we just don't know the value at this time
|
|
//
|
|
|
|
return pstrVal->Copy( "", 0 );
|
|
}
|
|
}
|
|
|
|
//
|
|
// Second: Is this a header name (prefixed with HTTP_)
|
|
//
|
|
|
|
if ( pW3Context != NULL &&
|
|
pszVariableName[ 0 ] == 'H' &&
|
|
!strncmp( pszVariableName, "HTTP_" , 5 ) )
|
|
{
|
|
STACK_STRA( strVariable, 256 );
|
|
|
|
hr = strVariable.Copy( pszVariableName + 5 );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
// Change '_' to '-'
|
|
PCHAR pszCursor = strchr( strVariable.QueryStr(), '_' );
|
|
while ( pszCursor != NULL )
|
|
{
|
|
*pszCursor++ = '-';
|
|
pszCursor = strchr( pszCursor, '_' );
|
|
}
|
|
|
|
return pW3Context->QueryRequest()->GetHeader( strVariable,
|
|
pstrVal );
|
|
}
|
|
|
|
//
|
|
// Third: Is this an uncanonicalized header name (prefixed with HEADER_)
|
|
//
|
|
|
|
if ( pW3Context != NULL &&
|
|
pszVariableName[ 0 ] == 'H' &&
|
|
!strncmp( pszVariableName, "HEADER_" , 7 ) )
|
|
{
|
|
STACK_STRA( strVariable, 256 );
|
|
|
|
hr = strVariable.Copy( pszVariableName + 7 );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return pW3Context->QueryRequest()->GetHeader( strVariable,
|
|
pstrVal );
|
|
}
|
|
|
|
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_INDEX );
|
|
}
|
|
|
|
//static
|
|
HRESULT
|
|
SERVER_VARIABLE_HASH::GetServerVariableW(
|
|
W3_CONTEXT * pW3Context,
|
|
CHAR * pszVariableName,
|
|
STRU * pstrVal
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Get server variable
|
|
|
|
Arguments:
|
|
|
|
pW3Context - W3_CONTEXT with request state. Can be NULL if we are
|
|
just determining whether the server variable requested is
|
|
valid. If NULL, we will return an empty string (and success)
|
|
if the variable requested is valid.
|
|
pszVariable - Variable name to retrieve
|
|
pstrVal - Filled with variable on success
|
|
|
|
Return Value:
|
|
|
|
HRESULT
|
|
|
|
--*/
|
|
{
|
|
HRESULT hr = S_OK;
|
|
PFN_SERVER_VARIABLE_ROUTINE pfnRoutine = NULL;
|
|
PFN_SERVER_VARIABLE_ROUTINE_W pfnRoutineW = NULL;
|
|
|
|
hr = SERVER_VARIABLE_HASH::GetServerVariableRoutine( pszVariableName,
|
|
&pfnRoutine,
|
|
&pfnRoutineW );
|
|
if ( SUCCEEDED(hr) )
|
|
{
|
|
if (pW3Context == NULL)
|
|
{
|
|
//
|
|
// Just return empty string to signify that the variable is
|
|
// valid but we just don't know the value at this time
|
|
//
|
|
|
|
return pstrVal->Copy( L"", 0 );
|
|
}
|
|
|
|
if (pfnRoutineW != NULL)
|
|
{
|
|
//
|
|
// This server-variable contains real unicode data and there
|
|
// is a unicode ServerVariable routine for this
|
|
//
|
|
|
|
return pfnRoutineW( pW3Context, pstrVal );
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// No unicode version, use the ANSI version and just wide'ize it
|
|
//
|
|
STACK_STRA( straVal, 256);
|
|
|
|
DBG_ASSERT( pfnRoutine != NULL );
|
|
|
|
if (FAILED(hr = pfnRoutine( pW3Context, &straVal )) ||
|
|
FAILED(hr = pstrVal->CopyA( straVal.QueryStr(),
|
|
straVal.QueryCCH() )))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
}
|
|
|
|
return HRESULT_FROM_WIN32( ERROR_INVALID_INDEX );
|
|
}
|
|
|
|
//
|
|
// Server variable functions
|
|
//
|
|
|
|
HRESULT
|
|
GetServerVariableQueryString(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
return pW3Context->QueryRequest()->GetQueryStringA(pstrVal);
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableAllHttp(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
return pW3Context->QueryRequest()->GetAllHeaders( pstrVal, TRUE );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableAllRaw(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
return pW3Context->QueryRequest()->GetAllHeaders( pstrVal, FALSE );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableContentLength(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
const CHAR * pszContentLength;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
if ( pW3Context->QueryRequest()->IsChunkedRequest() )
|
|
{
|
|
pszContentLength = "-1";
|
|
}
|
|
else
|
|
{
|
|
pszContentLength = pW3Context->QueryRequest()->GetHeader( HttpHeaderContentLength );
|
|
if ( pszContentLength == NULL )
|
|
{
|
|
pszContentLength = "0";
|
|
}
|
|
}
|
|
|
|
return pstrVal->Copy( pszContentLength );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableContentType(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
LPCSTR pszContentType = pW3Context->QueryRequest()->
|
|
GetHeader( HttpHeaderContentType );
|
|
if ( pszContentType == NULL )
|
|
{
|
|
pszContentType = "";
|
|
}
|
|
|
|
return pstrVal->Copy( pszContentType );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableInstanceId(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
CHAR pszId[16];
|
|
_itoa( pW3Context->QueryRequest()->QuerySiteId(), pszId, 10 );
|
|
|
|
return pstrVal->Copy( pszId );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableRemoteHost(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
//
|
|
// If we have a resolved DNS name, then use it. Otherwise just
|
|
// return the address
|
|
//
|
|
|
|
hr = pW3Context->QueryMainContext()->GetRemoteDNSName( pstrVal );
|
|
if ( hr == HRESULT_FROM_WIN32( ERROR_NOT_SUPPORTED ) )
|
|
{
|
|
hr = GetServerVariableRemoteAddr( pW3Context, pstrVal );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableRemoteAddr(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
HRESULT hr = S_OK;
|
|
W3_REQUEST * pW3Request = pW3Context->QueryRequest();
|
|
DBG_ASSERT( pW3Request != NULL );
|
|
|
|
if( pW3Request->QueryRemoteAddressType() == AF_INET )
|
|
{
|
|
DWORD dwAddr = ntohl( pW3Request->QueryIPv4RemoteAddress() );
|
|
hr = TranslateIpAddressToStr( dwAddr, pstrVal );
|
|
}
|
|
else if( pW3Request->QueryRemoteAddressType() == AF_INET6 )
|
|
{
|
|
SOCKADDR_IN6 IPv6RemoteAddress;
|
|
CHAR szNumericRemoteAddress[ NI_MAXHOST ];
|
|
|
|
IPv6RemoteAddress.sin6_family = AF_INET6;
|
|
IPv6RemoteAddress.sin6_port = pW3Request->QueryRemotePort();
|
|
IPv6RemoteAddress.sin6_flowinfo = ( ( PSOCKADDR_IN6 )
|
|
pW3Request->QueryRemoteSockAddress() )->sin6_flowinfo;
|
|
IPv6RemoteAddress.sin6_addr =
|
|
*pW3Request->QueryIPv6RemoteAddress();
|
|
IPv6RemoteAddress.sin6_scope_id = ( ( PSOCKADDR_IN6 )
|
|
pW3Request->QueryRemoteSockAddress() )->sin6_scope_id;
|
|
|
|
if( getnameinfo( ( LPSOCKADDR )&IPv6RemoteAddress,
|
|
sizeof( IPv6RemoteAddress ),
|
|
szNumericRemoteAddress,
|
|
sizeof( szNumericRemoteAddress ),
|
|
NULL,
|
|
0,
|
|
NI_NUMERICHOST ) != 0 )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( WSAGetLastError() );
|
|
}
|
|
else
|
|
{
|
|
hr = pstrVal->Copy( szNumericRemoteAddress );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableRemotePort(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
W3_REQUEST * pW3Request = pW3Context->QueryRequest();
|
|
CHAR szPort[33]; // 33 is max buffer used by _ultoa
|
|
USHORT uPort;
|
|
|
|
DBG_ASSERT( pW3Request != NULL );
|
|
|
|
uPort = htons( pW3Request->QueryRemotePort() );
|
|
|
|
_ultoa( uPort, szPort, 10 );
|
|
|
|
return pstrVal->Copy( szPort );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableServerName(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
STACK_STRU( strValW, 32 );
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
//
|
|
// If the client sent a host name, use it.
|
|
//
|
|
|
|
HRESULT hr = pW3Context->QueryRequest()->GetHostAddr( &strValW );
|
|
if ( FAILED( hr ))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return pstrVal->CopyW( strValW.QueryStr() );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableServerNameW(
|
|
W3_CONTEXT *pW3Context,
|
|
STRU *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
//
|
|
// If the client sent a host name, use it.
|
|
//
|
|
|
|
return pW3Context->QueryRequest()->GetHostAddr( pstrVal );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableServerPort(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
USHORT port;
|
|
|
|
W3_REQUEST * pW3Request = pW3Context->QueryRequest();
|
|
DBG_ASSERT( pW3Request != NULL );
|
|
|
|
port = ntohs( pW3Request->QueryLocalPort() );
|
|
|
|
CHAR szPort[8];
|
|
_itoa( port, szPort, 10 );
|
|
|
|
return pstrVal->Copy( szPort );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariablePathInfo(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
URL_CONTEXT *pUrlContext;
|
|
BOOL fDeleteHandler = FALSE;
|
|
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
|
|
//
|
|
// We might be called in an early filter where URL context isn't available
|
|
//
|
|
|
|
if ( pUrlContext == NULL )
|
|
{
|
|
pstrVal->Reset();
|
|
return NO_ERROR;
|
|
}
|
|
|
|
W3_URL_INFO *pUrlInfo = pUrlContext->QueryUrlInfo();
|
|
DBG_ASSERT( pUrlInfo != NULL );
|
|
|
|
W3_SITE *pSite = pW3Context->QuerySite();
|
|
DBG_ASSERT( pSite != NULL );
|
|
|
|
W3_HANDLER *pHandler;
|
|
pHandler = pW3Context->QueryHandler();
|
|
|
|
HRESULT hr;
|
|
|
|
//
|
|
// If we have no handler, yet we have a URL_CONTEXT, then this
|
|
// must be GetServerVariable() call before the handler state
|
|
// Determine the handler temporarily so we can make right call
|
|
// on variable. Only need to do this for ANSI variable since this
|
|
// problem only happens for filter calls
|
|
//
|
|
|
|
if ( pHandler == NULL )
|
|
{
|
|
hr = pW3Context->InternalDetermineHandler( &pHandler, FALSE );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
goto Finished;
|
|
}
|
|
|
|
DBG_ASSERT( pHandler != NULL );
|
|
|
|
fDeleteHandler = TRUE;
|
|
}
|
|
|
|
//
|
|
// In the case of script maps, if AllowPathInfoForScriptMappings
|
|
// is not set for the site, we ignore path info, it is
|
|
// just the URL
|
|
//
|
|
|
|
if ( pHandler != NULL &&
|
|
pHandler->QueryScriptMapEntry() &&
|
|
!pSite->QueryAllowPathInfoForScriptMappings() )
|
|
{
|
|
STACK_STRU (strUrl, MAX_PATH);
|
|
|
|
if (FAILED(hr = pW3Context->QueryRequest()->GetUrl( &strUrl )) ||
|
|
FAILED(hr = pstrVal->CopyW( strUrl.QueryStr() )))
|
|
{
|
|
goto Finished;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
hr = pstrVal->CopyW( pUrlInfo->QueryPathInfo()->QueryStr() );
|
|
}
|
|
|
|
Finished:
|
|
|
|
if ( fDeleteHandler )
|
|
{
|
|
delete pHandler;
|
|
pHandler = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariablePathInfoW(
|
|
W3_CONTEXT *pW3Context,
|
|
STRU *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
URL_CONTEXT *pUrlContext;
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
|
|
//
|
|
// We might be called in an early filter where URL context isn't available
|
|
//
|
|
|
|
if ( pUrlContext == NULL )
|
|
{
|
|
pstrVal->Reset();
|
|
return NO_ERROR;
|
|
}
|
|
|
|
W3_URL_INFO *pUrlInfo = pUrlContext->QueryUrlInfo();
|
|
DBG_ASSERT( pUrlInfo != NULL );
|
|
|
|
W3_SITE *pSite = pW3Context->QuerySite();
|
|
DBG_ASSERT( pSite != NULL );
|
|
|
|
W3_HANDLER *pHandler;
|
|
pHandler = pW3Context->QueryHandler();
|
|
|
|
//
|
|
// In the case of script maps, if AllowPathInfoForScriptMappings
|
|
// is not set for the site, we ignore path info, it is
|
|
// just the URL
|
|
//
|
|
|
|
if ( pHandler != NULL &&
|
|
pHandler->QueryScriptMapEntry() &&
|
|
!pSite->QueryAllowPathInfoForScriptMappings() )
|
|
{
|
|
return pW3Context->QueryRequest()->GetUrl( pstrVal );
|
|
}
|
|
else
|
|
{
|
|
return pstrVal->Copy( pUrlInfo->QueryPathInfo()->QueryStr() );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariablePathTranslated(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
HRESULT hr;
|
|
BOOL fDeleteHandler = FALSE;
|
|
|
|
URL_CONTEXT *pUrlContext;
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
|
|
if ( pUrlContext == NULL )
|
|
{
|
|
return pstrVal->Copy( "" );
|
|
}
|
|
|
|
W3_URL_INFO *pUrlInfo = pUrlContext->QueryUrlInfo();
|
|
DBG_ASSERT(pUrlInfo != NULL);
|
|
|
|
W3_SITE *pSite = pW3Context->QuerySite();
|
|
DBG_ASSERT(pSite != NULL);
|
|
|
|
W3_HANDLER *pHandler;
|
|
pHandler = pW3Context->QueryHandler();
|
|
|
|
//
|
|
// If we have no handler, yet we have a URL_CONTEXT, then this
|
|
// must be GetServerVariable() call before the handler state
|
|
// Determine the handler temporarily so we can make right call
|
|
// on variable. Only need to do this for ANSI variable since this
|
|
// problem only happens for filter calls
|
|
//
|
|
|
|
if ( pHandler == NULL )
|
|
{
|
|
hr = pW3Context->InternalDetermineHandler( &pHandler, FALSE );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
DBG_ASSERT( pHandler != NULL );
|
|
|
|
fDeleteHandler = TRUE;
|
|
}
|
|
|
|
BOOL fUsePathInfo;
|
|
if ( pHandler != NULL &&
|
|
pHandler->QueryScriptMapEntry() &&
|
|
!pSite->QueryAllowPathInfoForScriptMappings() )
|
|
{
|
|
fUsePathInfo = FALSE;
|
|
}
|
|
else
|
|
{
|
|
fUsePathInfo = TRUE;
|
|
}
|
|
|
|
STACK_STRU (struPathTranslated, 256);
|
|
//
|
|
// This is a new virtual path to have filters map
|
|
//
|
|
|
|
hr = pUrlInfo->GetPathTranslated( pW3Context,
|
|
fUsePathInfo,
|
|
&struPathTranslated );
|
|
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pstrVal->CopyW( struPathTranslated.QueryStr() );
|
|
}
|
|
|
|
if ( fDeleteHandler )
|
|
{
|
|
delete pHandler;
|
|
pHandler = NULL;
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariablePathTranslatedW(
|
|
W3_CONTEXT *pW3Context,
|
|
STRU *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
URL_CONTEXT *pUrlContext;
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
|
|
if ( pUrlContext == NULL )
|
|
{
|
|
return pstrVal->Copy( L"" );
|
|
}
|
|
|
|
W3_URL_INFO *pUrlInfo = pUrlContext->QueryUrlInfo();
|
|
DBG_ASSERT(pUrlInfo != NULL);
|
|
|
|
W3_SITE *pSite = pW3Context->QuerySite();
|
|
DBG_ASSERT(pSite != NULL);
|
|
|
|
W3_HANDLER *pHandler;
|
|
pHandler = pW3Context->QueryHandler();
|
|
|
|
BOOL fUsePathInfo;
|
|
if ( pHandler != NULL &&
|
|
pHandler->QueryScriptMapEntry() &&
|
|
!pSite->QueryAllowPathInfoForScriptMappings() )
|
|
{
|
|
fUsePathInfo = FALSE;
|
|
}
|
|
else
|
|
{
|
|
fUsePathInfo = TRUE;
|
|
}
|
|
|
|
//
|
|
// This is a new virtual path to have filters map
|
|
//
|
|
|
|
return pUrlInfo->GetPathTranslated( pW3Context,
|
|
fUsePathInfo,
|
|
pstrVal );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableRequestMethod(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
return pW3Context->QueryRequest()->GetVerbString( pstrVal );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableServerPortSecure(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
if ( pW3Context->QueryRequest()->IsSecureRequest() )
|
|
{
|
|
return pstrVal->Copy("1", 1);
|
|
}
|
|
|
|
return pstrVal->Copy("0", 1);
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableServerSoftware(
|
|
W3_CONTEXT *,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
return pstrVal->Copy( SERVER_SOFTWARE_STRING );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableUrl(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
URL_CONTEXT * pUrlContext;
|
|
W3_URL_INFO * pUrlInfo;
|
|
STACK_STRU( strUrl, 256 );
|
|
HRESULT hr;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
//
|
|
// URL context can be NULL if an early filter is called GetServerVar()
|
|
//
|
|
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
if ( pUrlContext != NULL )
|
|
{
|
|
pUrlInfo = pUrlContext->QueryUrlInfo();
|
|
DBG_ASSERT( pUrlInfo != NULL );
|
|
|
|
return pstrVal->CopyW( pUrlInfo->QueryProcessedUrl()->QueryStr() );
|
|
}
|
|
else
|
|
{
|
|
hr = pW3Context->QueryRequest()->GetUrl( &strUrl );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return pstrVal->CopyW( strUrl.QueryStr() );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableUrlW(
|
|
W3_CONTEXT *pW3Context,
|
|
STRU *pstrVal
|
|
)
|
|
{
|
|
URL_CONTEXT * pUrlContext;
|
|
W3_URL_INFO * pUrlInfo;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
//
|
|
// URL context can be NULL if an early filter is called GetServerVar()
|
|
//
|
|
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
if ( pUrlContext != NULL )
|
|
{
|
|
pUrlInfo = pUrlContext->QueryUrlInfo();
|
|
DBG_ASSERT( pUrlInfo != NULL );
|
|
|
|
return pstrVal->Copy( pUrlInfo->QueryProcessedUrl()->QueryStr() );
|
|
}
|
|
else
|
|
{
|
|
return pW3Context->QueryRequest()->GetUrl( pstrVal );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableInstanceMetaPath(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
STRU *pstrMetaPath = pW3Context->QuerySite()->QueryMBPath();
|
|
DBG_ASSERT( pstrMetaPath );
|
|
|
|
return pstrVal->CopyW( pstrMetaPath->QueryStr() );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableLogonUser(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
W3_USER_CONTEXT *pUserContext;
|
|
pUserContext = pW3Context->QueryUserContext();
|
|
|
|
if ( pUserContext == NULL )
|
|
{
|
|
return pW3Context->QueryRequest()->GetRequestUserName( pstrVal );
|
|
}
|
|
else
|
|
{
|
|
return pstrVal->CopyW( pUserContext->QueryUserName() );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableLogonUserW(
|
|
W3_CONTEXT *pW3Context,
|
|
STRU *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
W3_USER_CONTEXT *pUserContext;
|
|
pUserContext = pW3Context->QueryUserContext();
|
|
|
|
if ( pUserContext == NULL )
|
|
{
|
|
return pstrVal->CopyA( pW3Context->QueryRequest()->QueryRequestUserName()->QueryStr() );
|
|
}
|
|
else
|
|
{
|
|
return pstrVal->Copy( pUserContext->QueryUserName() );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableRemoteUser(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
hr = pW3Context->QueryRequest()->GetRequestUserName( pstrVal );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if ( pstrVal->IsEmpty() )
|
|
{
|
|
W3_USER_CONTEXT *pUserContext;
|
|
pUserContext = pW3Context->QueryUserContext();
|
|
|
|
if ( pUserContext != NULL )
|
|
{
|
|
hr = pstrVal->CopyW( pUserContext->QueryRemoteUserName() );
|
|
}
|
|
else
|
|
{
|
|
hr = NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableRemoteUserW(
|
|
W3_CONTEXT *pW3Context,
|
|
STRU *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
STRA *pstrUserName = pW3Context->QueryRequest()->QueryRequestUserName();
|
|
|
|
if ( pstrUserName->IsEmpty() )
|
|
{
|
|
W3_USER_CONTEXT *pUserContext;
|
|
pUserContext = pW3Context->QueryUserContext();
|
|
|
|
if ( pUserContext != NULL )
|
|
{
|
|
return pstrVal->Copy( pUserContext->QueryRemoteUserName() );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return pstrVal->CopyA( pstrUserName->QueryStr() );
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableAuthType(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
DBG_ASSERT( pstrVal != NULL );
|
|
|
|
HRESULT hr = S_OK;
|
|
|
|
W3_USER_CONTEXT *pUserContext = pW3Context->QueryUserContext();
|
|
|
|
if ( pUserContext != NULL )
|
|
{
|
|
if ( pUserContext->QueryAuthType() == MD_ACCESS_MAP_CERT )
|
|
{
|
|
hr = pstrVal->Copy( "SSL/PCT" );
|
|
}
|
|
else if ( pUserContext->QueryAuthType() == MD_AUTH_ANONYMOUS )
|
|
{
|
|
hr = pstrVal->Copy( "" );
|
|
}
|
|
else if ( pUserContext->QueryAuthType() == MD_AUTH_PASSPORT )
|
|
{
|
|
hr = pstrVal->Copy( "PASSPORT" );
|
|
}
|
|
else
|
|
{
|
|
hr = pW3Context->QueryRequest()->GetAuthType( pstrVal );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
//
|
|
// If an filter checks this server variable in
|
|
// SF_NOTIFY_AUTHENTICATION, there won't be a pUserContext
|
|
// yet, but we need to give an answer based on the
|
|
// authorization header anyway to be compatible with
|
|
// legacy behavior.
|
|
//
|
|
|
|
hr = pW3Context->QueryRequest()->GetAuthType( pstrVal );
|
|
|
|
}
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableAuthPassword(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
HRESULT hr;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
hr = pW3Context->QueryRequest()->GetRequestPassword( pstrVal );
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
if ( pstrVal->IsEmpty() )
|
|
{
|
|
W3_USER_CONTEXT * pUserContext;
|
|
pUserContext = pW3Context->QueryUserContext();
|
|
|
|
if ( pUserContext != NULL )
|
|
{
|
|
hr = pstrVal->CopyW( pUserContext->QueryPassword() );
|
|
}
|
|
else
|
|
{
|
|
hr = NO_ERROR;
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableApplMdPath(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
STRU * pstrAppMetaPath = NULL;
|
|
URL_CONTEXT * pUrlContext;
|
|
HRESULT hr;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
if ( pUrlContext != NULL )
|
|
{
|
|
W3_METADATA *pMetaData = pUrlContext->QueryMetaData();
|
|
|
|
DBG_ASSERT( pMetaData != NULL );
|
|
|
|
pstrAppMetaPath = pMetaData->QueryAppMetaPath();
|
|
}
|
|
|
|
if( pstrAppMetaPath == NULL ||
|
|
pstrAppMetaPath->IsEmpty() )
|
|
{
|
|
//
|
|
// If we don't have APPL_MD_PATH, then the caller should
|
|
// get an empty string.
|
|
//
|
|
|
|
hr = pstrVal->Copy( "", 0 );
|
|
}
|
|
else
|
|
{
|
|
hr = pstrVal->CopyW( pstrAppMetaPath->QueryStr() );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableApplMdPathW(
|
|
W3_CONTEXT *pW3Context,
|
|
STRU *pstrVal
|
|
)
|
|
{
|
|
STRU * pstrAppMetaPath = NULL;
|
|
URL_CONTEXT * pUrlContext;
|
|
HRESULT hr;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
pUrlContext = pW3Context->QueryUrlContext();
|
|
if ( pUrlContext != NULL )
|
|
{
|
|
W3_METADATA *pMetaData = pUrlContext->QueryMetaData();
|
|
|
|
DBG_ASSERT( pMetaData != NULL );
|
|
|
|
pstrAppMetaPath = pMetaData->QueryAppMetaPath();
|
|
}
|
|
|
|
if( pstrAppMetaPath == NULL ||
|
|
pstrAppMetaPath->IsEmpty() )
|
|
{
|
|
//
|
|
// If we don't have APPL_MD_PATH, then the caller should
|
|
// get an empty string.
|
|
//
|
|
|
|
hr = pstrVal->Copy( L"" );
|
|
}
|
|
else
|
|
{
|
|
hr = pstrVal->Copy( pstrAppMetaPath->QueryStr() );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableApplPhysicalPath(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
DBG_ASSERT( pstrVal );
|
|
|
|
STACK_STRA( strAppMetaPath, MAX_PATH );
|
|
STACK_STRU( strAppUrl, MAX_PATH );
|
|
HRESULT hr = E_FAIL;
|
|
|
|
hr = GetServerVariableApplMdPath( pW3Context, &strAppMetaPath );
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// pstrAppMetaPath is a full metabase path:
|
|
// /LM/W3SVC/<site>/Root/...
|
|
//
|
|
// To convert it to a physical path we will use
|
|
// W3_STATE_URLINFO::MapPath, but this requires
|
|
// that we remove the metabase prefixes and build
|
|
// a Url string.
|
|
//
|
|
|
|
//
|
|
// Get the metabase path for the site root
|
|
//
|
|
|
|
W3_SITE *pSite = pW3Context->QuerySite();
|
|
DBG_ASSERT( pSite );
|
|
|
|
STRU *pstrSiteRoot = pSite->QueryMBRoot();
|
|
DBG_ASSERT( pstrSiteRoot );
|
|
|
|
//
|
|
// Make some assumptions about the site path and the AppMetaPath
|
|
// being well-formed. The AppMetaPath may not have a terminating
|
|
// /, but the site root will.
|
|
//
|
|
|
|
DBG_ASSERT( pstrSiteRoot->QueryCCH() >=
|
|
sizeof("/LM/W3SVC/1/Root/") - 1
|
|
);
|
|
|
|
if( strAppMetaPath.QueryCCH() < pstrSiteRoot->QueryCCH() - 1 )
|
|
{
|
|
//
|
|
// This indicates an invalid value for MD_APP_ROOT is sitting
|
|
// around. We need to bail if this is the case.
|
|
//
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Invalid MD_APP_ROOT detected (%s)\n",
|
|
strAppMetaPath.QueryStr()
|
|
));
|
|
|
|
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
DBG_ASSERT( strAppMetaPath.QueryCCH() >=
|
|
sizeof("/LM/W3SVC/1/Root/") - 2
|
|
);
|
|
|
|
//
|
|
// The AppUrl will be the metabase path -
|
|
// all the /LM/W3SVC/1/ROOT goo
|
|
//
|
|
|
|
CHAR * pszStartAppUrl = strAppMetaPath.QueryStr() +
|
|
(pstrSiteRoot->QueryCCH() - 1);
|
|
|
|
//
|
|
// The AppMetaPath may not have a terminating /, so if it is
|
|
// a site root pszStartAppUrl will be empty.
|
|
//
|
|
|
|
if( *pszStartAppUrl != '\0' )
|
|
{
|
|
if( *pszStartAppUrl != '/' )
|
|
{
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Invalid MD_APP_ROOT detected (%s)\n",
|
|
strAppMetaPath.QueryStr()
|
|
));
|
|
|
|
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
hr = strAppUrl.CopyA(
|
|
pszStartAppUrl,
|
|
strAppMetaPath.QueryCCH() - (pstrSiteRoot->QueryCCH() - 1)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hr = strAppUrl.Copy( L"/", 1 );
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
STACK_STRU (strAppPath, MAX_PATH);
|
|
//
|
|
// Convert to a physical path
|
|
//
|
|
|
|
hr = W3_STATE_URLINFO::MapPath( pW3Context,
|
|
strAppUrl,
|
|
&strAppPath,
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
if (SUCCEEDED(hr))
|
|
{
|
|
hr = pstrVal->CopyW(strAppPath.QueryStr());
|
|
|
|
//
|
|
// Ensure that the last character in the path
|
|
// is '\\'. There are legacy scripts that will
|
|
// concatenate filenames to this path, and many
|
|
// of them will break if we don't do this.
|
|
//
|
|
|
|
if ( SUCCEEDED( hr ) &&
|
|
*(pstrVal->QueryStr()+pstrVal->QueryCCH()-1) != '\\' )
|
|
{
|
|
hr = pstrVal->Append( "\\" );
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableApplPhysicalPathW(
|
|
W3_CONTEXT *pW3Context,
|
|
STRU *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
DBG_ASSERT( pstrVal );
|
|
|
|
STACK_STRU( strAppMetaPath, MAX_PATH );
|
|
STACK_STRU( strAppUrl, MAX_PATH );
|
|
HRESULT hr = E_FAIL;
|
|
|
|
hr = GetServerVariableApplMdPathW( pW3Context, &strAppMetaPath );
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
//
|
|
// pstrAppMetaPath is a full metabase path:
|
|
// /LM/W3SVC/<site>/Root/...
|
|
//
|
|
// To convert it to a physical path we will use
|
|
// W3_STATE_URLINFO::MapPath, but this requires
|
|
// that we remove the metabase prefixes and build
|
|
// a Url string.
|
|
//
|
|
|
|
//
|
|
// Get the metabase path for the site root
|
|
//
|
|
|
|
W3_SITE *pSite = pW3Context->QuerySite();
|
|
DBG_ASSERT( pSite );
|
|
|
|
STRU *pstrSiteRoot = pSite->QueryMBRoot();
|
|
DBG_ASSERT( pstrSiteRoot );
|
|
|
|
//
|
|
// Make some assumptions about the site path and the AppMetaPath
|
|
// being well-formed. The AppMetaPath may not have a terminating
|
|
// /, but the site root will.
|
|
//
|
|
|
|
DBG_ASSERT( pstrSiteRoot->QueryCCH() >=
|
|
sizeof("/LM/W3SVC/1/Root/") - 1
|
|
);
|
|
|
|
if( strAppMetaPath.QueryCCH() < pstrSiteRoot->QueryCCH() - 1 )
|
|
{
|
|
//
|
|
// This indicates an invalid value for MD_APP_ROOT is sitting
|
|
// around. We need to bail if this is the case.
|
|
//
|
|
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Invalid MD_APP_ROOT detected (%S)\n",
|
|
strAppMetaPath.QueryStr()
|
|
));
|
|
|
|
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
DBG_ASSERT( strAppMetaPath.QueryCCH() >=
|
|
sizeof("/LM/W3SVC/1/Root/") - 2
|
|
);
|
|
|
|
//
|
|
// The AppUrl will be the metabase path -
|
|
// all the /LM/W3SVC/1/ROOT goo
|
|
//
|
|
|
|
WCHAR * pszStartAppUrl = strAppMetaPath.QueryStr() +
|
|
(pstrSiteRoot->QueryCCH() - 1);
|
|
|
|
//
|
|
// The AppMetaPath may not have a terminating /, so if it is
|
|
// a site root pszStartAppUrl will be empty.
|
|
//
|
|
|
|
if( *pszStartAppUrl != L'\0' )
|
|
{
|
|
if( *pszStartAppUrl != L'/' )
|
|
{
|
|
DBGPRINTF(( DBG_CONTEXT,
|
|
"Invalid MD_APP_ROOT detected (%s)\n",
|
|
strAppMetaPath.QueryStr()
|
|
));
|
|
|
|
return HRESULT_FROM_WIN32(ERROR_INVALID_DATA);
|
|
}
|
|
|
|
hr = strAppUrl.Copy(
|
|
pszStartAppUrl,
|
|
strAppMetaPath.QueryCCH() - (pstrSiteRoot->QueryCCH() - 1)
|
|
);
|
|
}
|
|
else
|
|
{
|
|
hr = strAppUrl.Copy( L"/", 1 );
|
|
}
|
|
|
|
if( SUCCEEDED(hr) )
|
|
{
|
|
hr = W3_STATE_URLINFO::MapPath( pW3Context,
|
|
strAppUrl,
|
|
pstrVal,
|
|
FALSE,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL,
|
|
NULL
|
|
);
|
|
|
|
//
|
|
// Ensure that the last character in the path
|
|
// is '\\'. There are legacy scripts that will
|
|
// concatenate filenames to this path, and many
|
|
// of them will break if we don't do this.
|
|
//
|
|
|
|
if ( SUCCEEDED( hr ) &&
|
|
*(pstrVal->QueryStr()+pstrVal->QueryCCH()-1) != L'\\' )
|
|
{
|
|
hr = pstrVal->Append( L"\\" );
|
|
}
|
|
}
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableGatewayInterface(
|
|
W3_CONTEXT *,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
return pstrVal->Copy("CGI/1.1", 7);
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableLocalAddr(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
HRESULT hr = S_OK;
|
|
W3_REQUEST * pW3Request = pW3Context->QueryRequest();
|
|
DBG_ASSERT( pW3Request != NULL );
|
|
|
|
if( pW3Request->QueryLocalAddressType() == AF_INET )
|
|
{
|
|
DWORD dwAddr = ntohl( pW3Request->QueryIPv4LocalAddress() );
|
|
hr = TranslateIpAddressToStr( dwAddr, pstrVal );
|
|
}
|
|
else if( pW3Request->QueryLocalAddressType() == AF_INET6 )
|
|
{
|
|
SOCKADDR_IN6 IPv6LocalAddress;
|
|
CHAR szNumericLocalAddress[ NI_MAXHOST ];
|
|
|
|
IPv6LocalAddress.sin6_family = AF_INET6;
|
|
IPv6LocalAddress.sin6_port = pW3Request->QueryLocalPort();
|
|
IPv6LocalAddress.sin6_flowinfo = ( ( PSOCKADDR_IN6 )
|
|
pW3Request->QueryLocalSockAddress() )->sin6_flowinfo;
|
|
IPv6LocalAddress.sin6_addr =
|
|
*pW3Request->QueryIPv6LocalAddress();
|
|
IPv6LocalAddress.sin6_scope_id = ( ( PSOCKADDR_IN6 )
|
|
pW3Request->QueryLocalSockAddress() )->sin6_scope_id;
|
|
|
|
|
|
if( getnameinfo( ( LPSOCKADDR )&IPv6LocalAddress,
|
|
sizeof( IPv6LocalAddress ),
|
|
szNumericLocalAddress,
|
|
sizeof( szNumericLocalAddress ),
|
|
NULL,
|
|
0,
|
|
NI_NUMERICHOST ) != 0 )
|
|
{
|
|
hr = HRESULT_FROM_WIN32( WSAGetLastError() );
|
|
}
|
|
else
|
|
{
|
|
hr = pstrVal->Copy( szNumericLocalAddress );
|
|
}
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT( FALSE );
|
|
}
|
|
|
|
return hr;
|
|
}
|
|
|
|
HRESULT GetServerVariableHttps(
|
|
W3_CONTEXT *pW3Context,
|
|
STRA *pstrVal)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
if (pW3Context->QueryRequest()->IsSecureRequest())
|
|
{
|
|
return pstrVal->Copy("on", 2);
|
|
}
|
|
|
|
return pstrVal->Copy("off", 3);
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableHttpsKeySize(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
HTTP_SSL_INFO * pSslInfo;
|
|
CHAR achNum[ 64 ];
|
|
|
|
pSslInfo = pW3Context->QueryRequest()->QuerySslInfo();
|
|
if ( pSslInfo == NULL )
|
|
{
|
|
achNum[ 0 ] = '\0';
|
|
}
|
|
else
|
|
{
|
|
_itoa( pSslInfo->ConnectionKeySize,
|
|
achNum,
|
|
10 );
|
|
}
|
|
|
|
return pstrVal->Copy( achNum );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableClientCertIssuer(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
CERTIFICATE_CONTEXT * pCertContext;
|
|
|
|
pCertContext = pW3Context->QueryMainContext()->QueryCertificateContext();
|
|
if ( pCertContext == NULL )
|
|
{
|
|
return pstrVal->Copy( "", 0 );
|
|
}
|
|
else
|
|
{
|
|
return pCertContext->GetIssuer( pstrVal );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableClientCertSubject(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
CERTIFICATE_CONTEXT * pCertContext;
|
|
|
|
pCertContext = pW3Context->QueryMainContext()->QueryCertificateContext();
|
|
if ( pCertContext == NULL )
|
|
{
|
|
return pstrVal->Copy( "", 0 );
|
|
}
|
|
else
|
|
{
|
|
return pCertContext->GetSubject( pstrVal );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableClientCertCookie(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
CERTIFICATE_CONTEXT * pCertContext;
|
|
|
|
pCertContext = pW3Context->QueryMainContext()->QueryCertificateContext();
|
|
if ( pCertContext == NULL )
|
|
{
|
|
return pstrVal->Copy( "", 0 );
|
|
}
|
|
else
|
|
{
|
|
return pCertContext->GetCookie( pstrVal );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableClientCertSerialNumber(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
CERTIFICATE_CONTEXT * pCertContext;
|
|
|
|
pCertContext = pW3Context->QueryMainContext()->QueryCertificateContext();
|
|
if ( pCertContext == NULL )
|
|
{
|
|
return pstrVal->Copy( "", 0 );
|
|
}
|
|
else
|
|
{
|
|
return pCertContext->GetSerialNumber( pstrVal );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableClientCertFlags(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
CERTIFICATE_CONTEXT * pCertContext;
|
|
|
|
pCertContext = pW3Context->QueryMainContext()->QueryCertificateContext();
|
|
if ( pCertContext == NULL )
|
|
{
|
|
return pstrVal->Copy( "" );
|
|
}
|
|
else
|
|
{
|
|
// CertFlags - legacy value
|
|
// In IIS3 days client certificates were not verified by IIS
|
|
// so applications needed certificate flags to make
|
|
// their own decisions regarding trust
|
|
// Now only valid certificate allow access so value of 1 is
|
|
// the only one that is valid for post IIS3 versions of IIS
|
|
//
|
|
return pstrVal->Copy( "1" );
|
|
}
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableHttpsSecretKeySize(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
HTTP_SSL_INFO * pSslInfo;
|
|
CHAR achNum[ 64 ];
|
|
|
|
pSslInfo = pW3Context->QueryRequest()->QuerySslInfo();
|
|
if ( pSslInfo == NULL )
|
|
{
|
|
achNum[ 0 ] = '\0';
|
|
}
|
|
else
|
|
{
|
|
_itoa( pSslInfo->ServerCertKeySize,
|
|
achNum,
|
|
10 );
|
|
}
|
|
|
|
return pstrVal->Copy( achNum );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableHttpsServerIssuer(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
HTTP_SSL_INFO * pSslInfo;
|
|
LPCSTR pszVariable;
|
|
|
|
pSslInfo = pW3Context->QueryRequest()->QuerySslInfo();
|
|
if ( pSslInfo == NULL )
|
|
{
|
|
pszVariable = "";
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT( pSslInfo->pServerCertIssuer != NULL );
|
|
pszVariable = pSslInfo->pServerCertIssuer;
|
|
}
|
|
|
|
return pstrVal->Copy( pszVariable );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableHttpsServerSubject(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
HTTP_SSL_INFO * pSslInfo;
|
|
LPCSTR pszVariable;
|
|
|
|
pSslInfo = pW3Context->QueryRequest()->QuerySslInfo();
|
|
if ( pSslInfo == NULL )
|
|
{
|
|
pszVariable = "";
|
|
}
|
|
else
|
|
{
|
|
DBG_ASSERT( pSslInfo->pServerCertSubject != NULL );
|
|
pszVariable = pSslInfo->pServerCertSubject;
|
|
}
|
|
|
|
return pstrVal->Copy( pszVariable );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableHttpUrl(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
//
|
|
// HTTP_URL gets the raw url for the request. If a filter has
|
|
// modified the url the request object handles redirecting the
|
|
// RawUrl variable
|
|
//
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
return pW3Context->QueryRequest()->GetRawUrl( pstrVal );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableHttpVersion(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
//
|
|
// HTTP_VERSION returns the client version string
|
|
//
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
return pW3Context->QueryRequest()->GetVersionString( pstrVal );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableAppPoolId(
|
|
W3_CONTEXT *,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
//
|
|
// APP_POOL_ID returns the AppPoolId WAS started us with
|
|
//
|
|
|
|
return pstrVal->CopyW( (LPWSTR)UlAtqGetContextProperty(NULL,
|
|
ULATQ_PROPERTY_APP_POOL_ID) );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableAppPoolIdW(
|
|
W3_CONTEXT *,
|
|
STRU * pstrVal
|
|
)
|
|
{
|
|
//
|
|
// APP_POOL_ID returns the AppPoolId WAS started us with
|
|
//
|
|
|
|
return pstrVal->Copy( (LPWSTR)UlAtqGetContextProperty(NULL,
|
|
ULATQ_PROPERTY_APP_POOL_ID) );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableScriptTranslated(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
STACK_STRU( strCanonicalPath, MAX_PATH );
|
|
HRESULT hr = NOERROR;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
URL_CONTEXT *pUrlContext = pW3Context->QueryUrlContext();
|
|
DBG_ASSERT( pUrlContext != NULL );
|
|
|
|
hr = MakePathCanonicalizationProof( pUrlContext->QueryPhysicalPath()->QueryStr(),
|
|
&strCanonicalPath );
|
|
|
|
if ( FAILED( hr ) )
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return pstrVal->CopyW( strCanonicalPath.QueryStr() );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableScriptTranslatedW(
|
|
W3_CONTEXT * pW3Context,
|
|
STRU * pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
URL_CONTEXT *pUrlContext = pW3Context->QueryUrlContext();
|
|
DBG_ASSERT( pUrlContext != NULL );
|
|
|
|
return MakePathCanonicalizationProof( pUrlContext->QueryPhysicalPath()->QueryStr(),
|
|
pstrVal );
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableUnencodedUrl(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
|
|
W3_REQUEST *pW3Request = pW3Context->QueryRequest();
|
|
DBG_ASSERT( pW3Request != NULL );
|
|
|
|
return pW3Request->GetRawUrl(pstrVal);
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableSsiExecDisabled(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
W3_METADATA * pMetaData = NULL;
|
|
CHAR * pszResponse = NULL;
|
|
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
DBG_ASSERT( pstrVal != NULL );
|
|
|
|
pMetaData = pW3Context->QueryUrlContext()->QueryMetaData();
|
|
DBG_ASSERT( pMetaData != NULL );
|
|
|
|
pszResponse = ( pMetaData->QuerySSIExecDisabled() )? "1": "0";
|
|
|
|
return pstrVal->Copy( pszResponse );
|
|
}
|
|
|
|
|
|
HRESULT
|
|
GetServerVariableOriginalUrlW(
|
|
W3_CONTEXT * pW3Context,
|
|
STRU * pstrVal
|
|
)
|
|
{
|
|
DBG_ASSERT( pW3Context != NULL );
|
|
DBG_ASSERT( pstrVal != NULL );
|
|
|
|
return pW3Context->QueryMainContext()->QueryRequest()->GetOriginalFullUrl(pstrVal);
|
|
}
|
|
|
|
HRESULT
|
|
GetServerVariableOriginalUrl(
|
|
W3_CONTEXT * pW3Context,
|
|
STRA * pstrVal
|
|
)
|
|
{
|
|
STACK_STRU( struVal, 256);
|
|
HRESULT hr;
|
|
|
|
if (FAILED(hr = GetServerVariableOriginalUrlW(pW3Context, &struVal)) ||
|
|
FAILED(hr = pstrVal->CopyW(struVal.QueryStr())))
|
|
{
|
|
return hr;
|
|
}
|
|
|
|
return S_OK;
|
|
}
|
|
|