939 lines
23 KiB
C++
939 lines
23 KiB
C++
/**********************************************************************/
|
||
/** Microsoft Windows NT **/
|
||
/** Copyright(c) Microsoft Corp., 1995 **/
|
||
/**********************************************************************/
|
||
|
||
/*
|
||
extmap.cxx
|
||
|
||
This module contains the extension mapping to CGI or BGI scripts.
|
||
|
||
|
||
FILE HISTORY:
|
||
Johnl 22-Sep-1995 Created
|
||
|
||
*/
|
||
|
||
#include "w3p.hxx"
|
||
#include <rpc.h>
|
||
#include <rpcndr.h>
|
||
#include <mbstring.h>
|
||
|
||
//
|
||
// Name of the value under the parameters key containing the list of
|
||
// script extension to BGI/CGI binaries.
|
||
//
|
||
|
||
#define HTTP_EXT_MAPS "Script Map"
|
||
|
||
char Get[] = "GET";
|
||
|
||
#define GET_SIZE (sizeof("GET"))
|
||
|
||
//
|
||
// This is the maximum size for a script map extension
|
||
//
|
||
#define MAX_EXT_LEN 128
|
||
|
||
//
|
||
// This list is the extension maps found in the registry - they always get
|
||
// appended to the end of all extension mappings that are added to a particular
|
||
// URI.
|
||
//
|
||
|
||
static BOOL fInitialized = FALSE;
|
||
|
||
class EXT_MAP_ITEM
|
||
{
|
||
public:
|
||
|
||
EXT_MAP_ITEM( const char * pszExtension,
|
||
const char * pszImage,
|
||
const DWORD dwFlags,
|
||
const CHAR * pszExclusions,
|
||
const DWORD dwExclusionLength)
|
||
: _strExt ( pszExtension ),
|
||
_strImage ( pszImage ),
|
||
_GatewayType( GATEWAY_UNKNOWN ),
|
||
_cchExt ( 0 ),
|
||
_dwFlags ( dwFlags ),
|
||
_fGetValid (0),
|
||
_dwInclusionCount ( 0 ),
|
||
_ppszInclusionTable ( NULL ),
|
||
_pszInclusions ( NULL )
|
||
{
|
||
DWORD cch;
|
||
_fValid = _strExt.IsValid() && _strImage.IsValid() && ExpandImage();
|
||
|
||
if ( _fValid )
|
||
{
|
||
const CHAR * pchtmp = pszImage;
|
||
|
||
_cchExt = _strExt.QueryCCH();
|
||
|
||
//
|
||
// Determine if this is a CGI or BGI gateway
|
||
//
|
||
|
||
while ( pchtmp = strchr( pchtmp + 1, '.' ))
|
||
{
|
||
if ( !_strnicmp( pchtmp, ".exe", 4 ))
|
||
{
|
||
_GatewayType = GATEWAY_CGI;
|
||
}
|
||
else if ( !_strnicmp( pchtmp, ".dll", 4 ))
|
||
{
|
||
_GatewayType = GATEWAY_BGI;
|
||
}
|
||
}
|
||
|
||
if (!strcmp(pszExtension, "*"))
|
||
{
|
||
_fWildcard = TRUE;
|
||
_dwFlags |= MD_SCRIPTMAPFLAG_WILDCARD;
|
||
}
|
||
else
|
||
{
|
||
_fWildcard = FALSE;
|
||
_dwFlags &= ~MD_SCRIPTMAPFLAG_WILDCARD;
|
||
}
|
||
|
||
if (pszExclusions != NULL)
|
||
{
|
||
const CHAR *pszTemp;
|
||
char *pszDest;
|
||
|
||
_pszInclusions = new char[dwExclusionLength];
|
||
|
||
if (_pszInclusions == NULL)
|
||
{
|
||
_fValid = FALSE;
|
||
return;
|
||
}
|
||
|
||
_dwInclusionCount = 1;
|
||
pszTemp = pszExclusions;
|
||
pszDest = _pszInclusions;
|
||
|
||
while (*pszTemp != '\0')
|
||
{
|
||
CHAR ch;
|
||
|
||
ch = *pszTemp;
|
||
pszTemp++;
|
||
|
||
if (ch != ',')
|
||
{
|
||
*pszDest = ch;
|
||
}
|
||
else
|
||
{
|
||
*pszDest = '\0';
|
||
|
||
_dwInclusionCount++;
|
||
}
|
||
|
||
pszDest++;
|
||
|
||
}
|
||
|
||
*pszDest = '\0';
|
||
|
||
_ppszInclusionTable = new char *[_dwInclusionCount];
|
||
|
||
if (_ppszInclusionTable == NULL)
|
||
{
|
||
_fValid = FALSE;
|
||
return;
|
||
}
|
||
else
|
||
{
|
||
DWORD i;
|
||
DWORD dwPos;
|
||
|
||
pszTemp = _pszInclusions;
|
||
|
||
i = 0;
|
||
|
||
do {
|
||
|
||
_ppszInclusionTable[i] = (CHAR *)pszTemp;
|
||
|
||
if ( _fGetValid )
|
||
{
|
||
dwPos = 0;
|
||
}
|
||
|
||
while (*pszTemp != '\0')
|
||
{
|
||
if (dwPos < GET_SIZE)
|
||
{
|
||
if (*pszTemp == Get[dwPos])
|
||
{
|
||
dwPos++;
|
||
|
||
if (dwPos == (GET_SIZE - 1))
|
||
{
|
||
if (*(pszTemp+1) == '\0')
|
||
{
|
||
_fGetValid = TRUE;
|
||
}
|
||
else
|
||
{
|
||
dwPos = GET_SIZE;
|
||
}
|
||
}
|
||
}
|
||
else
|
||
{
|
||
dwPos = GET_SIZE;
|
||
}
|
||
}
|
||
|
||
pszTemp++;
|
||
}
|
||
|
||
DBG_ASSERT(*pszTemp == '\0');
|
||
|
||
pszTemp++;
|
||
|
||
i++;
|
||
|
||
} while (i < _dwInclusionCount );
|
||
}
|
||
}
|
||
else
|
||
{
|
||
_dwInclusionCount = 0;
|
||
_ppszInclusionTable = NULL;
|
||
_pszInclusions = NULL;
|
||
}
|
||
}
|
||
}
|
||
|
||
~EXT_MAP_ITEM( )
|
||
{
|
||
delete _ppszInclusionTable;
|
||
delete _pszInclusions;
|
||
}
|
||
|
||
|
||
GATEWAY_TYPE QueryGatewayType( VOID ) const
|
||
{ return _GatewayType; }
|
||
|
||
const CHAR * QueryScript( VOID ) const
|
||
{ return _strImage.QueryStr(); }
|
||
|
||
const CHAR * QueryExtension( VOID ) const
|
||
{ return _strExt.QueryStr(); }
|
||
|
||
const BOOL AllowedOnReadDir()
|
||
{ return _dwFlags & MD_SCRIPTMAPFLAG_SCRIPT; }
|
||
|
||
const DWORD QueryFlags()
|
||
{ return _dwFlags; }
|
||
|
||
DWORD QueryCCHExt( VOID ) const
|
||
{ return _cchExt; }
|
||
|
||
BOOL IsValid( VOID ) const
|
||
{ return _fValid; }
|
||
|
||
BOOL IsWildCard( VOID ) const
|
||
{ return _fWildcard; }
|
||
|
||
BOOL IsGetValid( VOID ) const
|
||
{ return _fGetValid; }
|
||
|
||
BOOL ExpandImage( VOID );
|
||
|
||
BOOL CheckInclusions(
|
||
const CHAR *pszVerb
|
||
);
|
||
|
||
LIST_ENTRY _ListEntry;
|
||
|
||
private:
|
||
|
||
STR _strExt;
|
||
STR _strImage;
|
||
DWORD _cchExt;
|
||
GATEWAY_TYPE _GatewayType;
|
||
DWORD _fValid:1;
|
||
DWORD _fWildcard:1;
|
||
DWORD _fGetValid:1;
|
||
DWORD _dwFlags;
|
||
DWORD _dwInclusionCount;
|
||
CHAR **_ppszInclusionTable;
|
||
CHAR *_pszInclusions;
|
||
};
|
||
|
||
|
||
BOOL
|
||
EXT_MAP_ITEM::ExpandImage( VOID )
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Expand any embedded environment variables in the image.
|
||
|
||
Return Value:
|
||
|
||
TRUE if successful, FALSE if not.
|
||
|
||
--*/
|
||
{
|
||
DWORD cbRet = 0;
|
||
TCHAR achBuffer[ MAX_PATH + 1 ];
|
||
DWORD cbBufLen = sizeof( achBuffer );
|
||
|
||
cbRet = ExpandEnvironmentStringsA( _strImage.QueryStr(),
|
||
achBuffer,
|
||
cbBufLen );
|
||
if ( !cbRet || ( cbRet > cbBufLen ) )
|
||
{
|
||
return FALSE;
|
||
}
|
||
else
|
||
{
|
||
return _strImage.Copy( achBuffer );
|
||
}
|
||
}
|
||
|
||
//
|
||
// Private globals.
|
||
//
|
||
|
||
BOOL
|
||
W3_METADATA::BuildExtMap(
|
||
CHAR *pszExtMapList
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Builds the extension mapping into the metadata. The input string is
|
||
a multi-sz of comma seperated ext, image name strings.
|
||
|
||
Return Value:
|
||
|
||
TRUE if successfull, FALSE if not.
|
||
|
||
--*/
|
||
{
|
||
EXT_MAP_ITEM * pExtMap;
|
||
EXT_MAP_ITEM * pWCExtMapItem;
|
||
LIST_ENTRY * pEntry;
|
||
|
||
m_fAnyExtAllowedOnReadDir = FALSE;
|
||
|
||
m_dwMaxExtLen = 0;
|
||
|
||
do
|
||
{
|
||
|
||
CHAR *pszExt;
|
||
CHAR *pszImage;
|
||
CHAR *pszFlags;
|
||
CHAR *pszExclusions;
|
||
CHAR *pszTemp;
|
||
CHAR *pszTemp2;
|
||
CHAR *pszTemp3;
|
||
DWORD dwExclusionSize;
|
||
DWORD dwExtSize;
|
||
|
||
pszExt = pszExtMapList;
|
||
|
||
// Find the end of the extension, and temporarily NULL terminate it.
|
||
|
||
pszImage = strchr(pszExt, ',');
|
||
|
||
if (pszImage == NULL) {
|
||
// Bad script map entry
|
||
SetLastError(ERROR_INVALID_DATA);
|
||
return FALSE;
|
||
}
|
||
|
||
pszTemp = pszImage++;
|
||
*pszTemp = '\0';
|
||
|
||
pszFlags = strchr(pszImage, ',');
|
||
|
||
if (pszFlags == NULL) {
|
||
// Bad script map entry
|
||
SetLastError(ERROR_INVALID_DATA);
|
||
return FALSE;
|
||
}
|
||
|
||
pszTemp2 = pszFlags++;
|
||
*pszTemp2 = '\0';
|
||
|
||
//
|
||
// HOTFIX: make sure the extension is not too long to be copied to
|
||
// our static buffer.
|
||
//
|
||
dwExtSize = strlen(pszExt);
|
||
if (dwExtSize > MAX_EXT_LEN) {
|
||
// Bad script map entry
|
||
SetLastError(ERROR_INVALID_DATA);
|
||
return FALSE;
|
||
} else if (dwExtSize > m_dwMaxExtLen) {
|
||
m_dwMaxExtLen = dwExtSize;
|
||
}
|
||
|
||
//
|
||
// See if there's any excluded methods. If there are, break them out.
|
||
//
|
||
|
||
pszExclusions = strchr(pszFlags, ',');
|
||
|
||
if (pszExclusions != NULL)
|
||
{
|
||
pszTemp3 = pszExclusions++;
|
||
*pszTemp3 = '\0';
|
||
dwExclusionSize = strlen(pszExclusions) + 1;
|
||
pszExtMapList = pszExclusions + dwExclusionSize;
|
||
}
|
||
else
|
||
{
|
||
pszExtMapList = pszFlags + strlen(pszFlags) + 1;
|
||
dwExclusionSize = 0;
|
||
}
|
||
|
||
//
|
||
// HOTFIX: Now convert extension to lower case so we can avoid
|
||
// multi-byte string compares that cause lock contention.
|
||
//
|
||
|
||
IISstrlwr( (PUCHAR) pszExt );
|
||
|
||
//
|
||
// Note we OR in the notransmit flag on *all* script mappings!
|
||
//
|
||
|
||
pExtMap = new EXT_MAP_ITEM( pszExt,
|
||
pszImage,
|
||
((DWORD) atoi( pszFlags )),
|
||
pszExclusions,
|
||
dwExclusionSize);
|
||
|
||
*pszTemp = ',';
|
||
*pszTemp2 = ',';
|
||
|
||
if (pszExclusions != NULL)
|
||
{
|
||
*pszTemp3 = '\0';
|
||
}
|
||
|
||
if ( !pExtMap ||
|
||
!pExtMap->IsValid() )
|
||
{
|
||
delete pExtMap;
|
||
|
||
return FALSE;
|
||
}
|
||
|
||
if (!pExtMap->IsWildCard())
|
||
{
|
||
InsertTailList( &m_ExtMapHead, &pExtMap->_ListEntry );
|
||
}
|
||
else
|
||
{
|
||
|
||
pWCExtMapItem = (EXT_MAP_ITEM *)QueryWildcardMapping();
|
||
|
||
if (pWCExtMapItem != NULL)
|
||
{
|
||
delete pWCExtMapItem;
|
||
}
|
||
|
||
SetWildcardMapping( pExtMap );
|
||
}
|
||
|
||
if ( pExtMap->QueryFlags() )
|
||
{
|
||
m_fAnyExtAllowedOnReadDir = TRUE;
|
||
}
|
||
|
||
} while ( *pszExtMapList != '\0');
|
||
|
||
return TRUE;
|
||
|
||
} // W3_METADATA::BuildExtMap
|
||
|
||
|
||
|
||
VOID
|
||
W3_METADATA::TerminateExtMap(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Cleans up the extension map list
|
||
|
||
--*/
|
||
{
|
||
LIST_ENTRY * pEntry;
|
||
EXT_MAP_ITEM * pExtMap;
|
||
|
||
while ( !IsListEmpty( &m_ExtMapHead ))
|
||
{
|
||
pExtMap = CONTAINING_RECORD( m_ExtMapHead.Flink,
|
||
EXT_MAP_ITEM,
|
||
_ListEntry );
|
||
|
||
RemoveEntryList( &pExtMap->_ListEntry );
|
||
|
||
delete pExtMap;
|
||
}
|
||
|
||
pExtMap = (EXT_MAP_ITEM *)QueryWildcardMapping();
|
||
|
||
if (pExtMap != NULL)
|
||
{
|
||
delete pExtMap;
|
||
}
|
||
|
||
|
||
} // W3_METADATA::TerminateExtMap
|
||
|
||
BOOL
|
||
EXT_MAP_ITEM::CheckInclusions(
|
||
const CHAR *pszVerb
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Check the extension map list to see if the input verb is included.
|
||
If it is, we return TRUE, otherwise we return FALSE.
|
||
--*/
|
||
{
|
||
DWORD i;
|
||
|
||
//
|
||
// Special case for EMPTY script map. Allow all verbs
|
||
//
|
||
|
||
if (0 == _dwInclusionCount)
|
||
{
|
||
return TRUE;
|
||
}
|
||
|
||
for (i = 0; i < _dwInclusionCount; i++)
|
||
{
|
||
if (!_stricmp(pszVerb, _ppszInclusionTable[i]))
|
||
{
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
return FALSE;
|
||
|
||
} // EXT_MAP_ITEM::CheckInclusions
|
||
|
||
BOOL
|
||
W3_METADATA::LookupExtMap(
|
||
IN const CHAR * pchExt,
|
||
IN BOOL fNoWildcards,
|
||
OUT STR * pstrGatewayImage,
|
||
OUT GATEWAY_TYPE * pGatewayType,
|
||
OUT DWORD * pcchExt,
|
||
OUT BOOL * pfImageInURL,
|
||
OUT BOOL * pfVerbExcluded,
|
||
OUT DWORD * pdwFlags,
|
||
IN const CHAR *pszVerb,
|
||
IN enum HTTP_VERB Verb,
|
||
IN OUT PVOID * ppvExtMapInfo
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Finds the admin specified mapping between a script extension and the
|
||
associated CGI or BGI binary to run (or load).
|
||
|
||
Arguments:
|
||
|
||
pchExt - Pointer to possible extension to be mapped (i.e., '.pl')
|
||
pstrGatewayImage - Receives the mapped binary image name
|
||
pGatewayType - Specifies whether this is a BGI, CGI or MAP extension type
|
||
pcchExt - Returns length of extension (including dot)
|
||
pfImageInURL - Indicates an image was found encoded in the URL and not
|
||
from a script extension mapping
|
||
pdwFlags - Returns extension flags
|
||
ppvExtMapInfo - Cached extension map info. If *ppvExtMapInfo is NULL on
|
||
input, then set to the matched PEXT_MAP_ITEM. If not NULL
|
||
on input, then it is used instead of doing lookup.
|
||
|
||
--*/
|
||
{
|
||
EXT_MAP_ITEM * pExtMapItem;
|
||
DWORD cchTillEOS;
|
||
BOOL fRet;
|
||
LIST_ENTRY * pEntry;
|
||
BOOL bFoundMatch = FALSE;
|
||
BOOL fUseExtMapInfo = *ppvExtMapInfo != NULL;
|
||
|
||
*pGatewayType = GATEWAY_UNKNOWN;
|
||
*pfVerbExcluded = FALSE;
|
||
|
||
//
|
||
// Check for wildcard mapping first
|
||
//
|
||
|
||
if (!fNoWildcards)
|
||
{
|
||
pExtMapItem = (EXT_MAP_ITEM *)QueryWildcardMapping();
|
||
|
||
if (pExtMapItem != NULL)
|
||
{
|
||
if (Verb == HTV_GET && pExtMapItem->IsGetValid())
|
||
{
|
||
bFoundMatch = TRUE;
|
||
}
|
||
else
|
||
{
|
||
// If verb is not included, don't return the * script map.
|
||
// Instead, continue to look for a script map match.
|
||
|
||
bFoundMatch = pExtMapItem->CheckInclusions( pszVerb );
|
||
}
|
||
}
|
||
}
|
||
|
||
//
|
||
// Look for the exact extension mapping if there's no wildcard
|
||
//
|
||
|
||
if (!bFoundMatch && pchExt != NULL)
|
||
{
|
||
if ( fUseExtMapInfo )
|
||
{
|
||
//
|
||
// If caller passed in a non-NULL pExtMapInfo, then use it
|
||
// instead of doing a manual lookup
|
||
//
|
||
|
||
if ( *ppvExtMapInfo != EXTMAP_UNKNOWN_PTR )
|
||
{
|
||
pExtMapItem = (EXT_MAP_ITEM*) *ppvExtMapInfo;
|
||
bFoundMatch = TRUE;
|
||
}
|
||
}
|
||
else
|
||
{
|
||
//
|
||
// This buffer, rgchExtBuffer, holds a copy of a portion of a URL
|
||
// which we are testing to see if it's a known extension. We copy
|
||
// into this buffer so we can convert the extension to lower case
|
||
// without disrupting the original.
|
||
//
|
||
CHAR rgchExtBuffer[MAX_EXT_LEN + 4];
|
||
DWORD dwLength;
|
||
|
||
DBG_ASSERT( *pchExt == '.' );
|
||
|
||
//
|
||
// HOTFIX: Now convert extension to lower case so we can avoid
|
||
// multi-byte string compares that cause lock contention.
|
||
//
|
||
// Since we don't want to risk modifying the orignal URL, we
|
||
// copy it into another buffer first.
|
||
//
|
||
|
||
cchTillEOS = strlen( pchExt );
|
||
|
||
dwLength = min(cchTillEOS, m_dwMaxExtLen + 1);
|
||
memcpy(rgchExtBuffer, pchExt, dwLength);
|
||
rgchExtBuffer[ dwLength ] = 0;
|
||
|
||
IISstrlwr( (PUCHAR) rgchExtBuffer );
|
||
|
||
//
|
||
// Look through the list of mappings
|
||
//
|
||
|
||
for ( pEntry = m_ExtMapHead.Flink;
|
||
!bFoundMatch && pEntry != &m_ExtMapHead;
|
||
pEntry = pEntry->Flink )
|
||
{
|
||
pExtMapItem = CONTAINING_RECORD( pEntry, EXT_MAP_ITEM, _ListEntry );
|
||
|
||
if ( cchTillEOS >= pExtMapItem->QueryCCHExt() &&
|
||
(pchExt[pExtMapItem->QueryCCHExt()] == '/' ||
|
||
pchExt[pExtMapItem->QueryCCHExt()] == '\0' ) &&
|
||
!memcmp( rgchExtBuffer,
|
||
pExtMapItem->QueryExtension(),
|
||
pExtMapItem->QueryCCHExt())
|
||
)
|
||
{
|
||
bFoundMatch = TRUE;
|
||
*ppvExtMapInfo = pExtMapItem;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
|
||
if (bFoundMatch)
|
||
{
|
||
*pGatewayType = pExtMapItem->QueryGatewayType();
|
||
*pcchExt = pExtMapItem->QueryCCHExt();
|
||
*pfImageInURL = FALSE;
|
||
*pdwFlags = pExtMapItem->QueryFlags();
|
||
|
||
//
|
||
// Check that verb is included. If it isn't, we're still going to return
|
||
// this item. Just indicate that the verb was excluded.
|
||
//
|
||
|
||
if (Verb != HTV_GET || !pExtMapItem->IsGetValid())
|
||
{
|
||
*pfVerbExcluded = !pExtMapItem->CheckInclusions(pszVerb);
|
||
}
|
||
|
||
fRet = pstrGatewayImage->Copy( pExtMapItem->QueryScript() );
|
||
|
||
if ( !_stricmp( pExtMapItem->QueryScript(), "nogateway" ) )
|
||
{
|
||
*pGatewayType = GATEWAY_NONE;
|
||
}
|
||
|
||
return fRet;
|
||
}
|
||
|
||
if ( !pchExt || fUseExtMapInfo )
|
||
{
|
||
if ( !fUseExtMapInfo )
|
||
{
|
||
*ppvExtMapInfo = EXTMAP_UNKNOWN_PTR;
|
||
}
|
||
|
||
return TRUE;
|
||
}
|
||
|
||
//
|
||
// Either the image will be specified in the URL or not found, so
|
||
// just indicate it's in the URL. Not found has precedence.
|
||
//
|
||
|
||
*pfImageInURL = TRUE;
|
||
*pdwFlags = 0;
|
||
|
||
//
|
||
// Look for CGI or BGI scripts in the URL itself
|
||
//
|
||
|
||
if ( cchTillEOS >= 4 &&
|
||
(*(pchExt+4) == TEXT('/') ||
|
||
*(pchExt+4) == TEXT('\0')) )
|
||
{
|
||
*pcchExt = 4;
|
||
|
||
//
|
||
// Don't confuse a menu map request with a gateway request
|
||
//
|
||
|
||
if ( !::_tcsnicmp( TEXT(".MAP"), pchExt, 4 ))
|
||
{
|
||
*pGatewayType = GATEWAY_MAP;
|
||
return TRUE;
|
||
}
|
||
|
||
if ( !::_tcsnicmp( TEXT(".EXE"), pchExt, 4 ) ||
|
||
!::_tcsnicmp( TEXT(".CGI"), pchExt, 4 ) ||
|
||
!::_tcsnicmp( TEXT(".COM"), pchExt, 4 ))
|
||
{
|
||
*pGatewayType = GATEWAY_CGI;
|
||
return TRUE;
|
||
}
|
||
else if (!::_tcsnicmp( TEXT(".DLL"), pchExt, 4 ) ||
|
||
!::_tcsnicmp( TEXT(".ISA"), pchExt, 4 ) )
|
||
{
|
||
*pGatewayType = GATEWAY_BGI;
|
||
return TRUE;
|
||
}
|
||
}
|
||
|
||
*ppvExtMapInfo = EXTMAP_UNKNOWN_PTR;
|
||
|
||
return TRUE;
|
||
} // W3_METADATA::LookupExtMap
|
||
|
||
|
||
APIERR
|
||
ReadRegistryExtMap(
|
||
VOID
|
||
)
|
||
/*++
|
||
|
||
Routine Description:
|
||
|
||
Builds the extension mapping from the registry
|
||
|
||
Return Value:
|
||
|
||
NO_ERROR if successful, win32 error code on failure
|
||
|
||
--*/
|
||
{
|
||
HKEY hkeyParam;
|
||
DWORD dwDisposition;
|
||
LIST_ENTRY pEntry;
|
||
APIERR err;
|
||
DWORD i = 0;
|
||
DWORD dwRegType;
|
||
MB mb( (IMDCOM*) g_pInetSvc->QueryMDObject() );
|
||
MULTISZ msz;
|
||
BOOL fNeedToWrite = FALSE;
|
||
|
||
if ( !fInitialized )
|
||
{
|
||
fInitialized = TRUE;
|
||
}
|
||
|
||
//
|
||
// Get the list
|
||
//
|
||
|
||
err = RegCreateKeyEx( HKEY_LOCAL_MACHINE,
|
||
W3_PARAMETERS_KEY "\\" HTTP_EXT_MAPS,
|
||
0,
|
||
0,
|
||
0,
|
||
KEY_READ,
|
||
NULL,
|
||
&hkeyParam,
|
||
&dwDisposition );
|
||
|
||
if( err != NO_ERROR )
|
||
{
|
||
TCP_PRINT(( DBG_CONTEXT,
|
||
"cannot open registry key, error %lu\n",
|
||
err ));
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
|
||
if ( !mb.Open( "/LM/W3SVC/",
|
||
METADATA_PERMISSION_READ|METADATA_PERMISSION_WRITE ) ||
|
||
!mb.GetMultisz( "",
|
||
MD_SCRIPT_MAPS,
|
||
IIS_MD_UT_FILE,
|
||
&msz ))
|
||
{
|
||
TCP_PRINT(( DBG_CONTEXT,
|
||
"cannot get the script maps from the metabase, error %d\n",
|
||
GetLastError() ));
|
||
|
||
return NO_ERROR;
|
||
}
|
||
|
||
while ( TRUE )
|
||
{
|
||
CHAR achExt[MAX_PATH+1];
|
||
CHAR achImage[MAX_PATH+1];
|
||
DWORD cchExt = sizeof( achExt );
|
||
DWORD cchImage = sizeof( achImage );
|
||
|
||
err = RegEnumValue( hkeyParam,
|
||
i++,
|
||
achExt,
|
||
&cchExt,
|
||
NULL,
|
||
&dwRegType,
|
||
(LPBYTE) achImage,
|
||
&cchImage );
|
||
|
||
if ( err == ERROR_NO_MORE_ITEMS )
|
||
{
|
||
err = NO_ERROR;
|
||
break;
|
||
}
|
||
|
||
if ( dwRegType == REG_SZ )
|
||
{
|
||
const CHAR * psz;
|
||
BOOL fFound = FALSE;
|
||
|
||
//
|
||
// Look for this script map in the metabase, if not found, add it
|
||
//
|
||
|
||
for ( psz = msz.First(); psz != NULL; psz = msz.Next( psz ) )
|
||
{
|
||
if ( !IISstrnicmp( (PUCHAR)achExt, (PUCHAR)psz, cchExt ))
|
||
{
|
||
fFound = TRUE;
|
||
break;
|
||
}
|
||
}
|
||
|
||
if ( !fFound )
|
||
{
|
||
STR str;
|
||
CHAR achFlags[32];
|
||
|
||
//
|
||
// Note these scripts are added w/o the Script bit and with
|
||
// the "never download" bit. In addition, we leave the
|
||
// method exclusion list blank.
|
||
//
|
||
|
||
_itoa( 0, achFlags, 10 );
|
||
|
||
if ( !str.Append( achExt ) ||
|
||
!str.Append( "," ) ||
|
||
!str.Append( achImage ) ||
|
||
!str.Append( "," ) ||
|
||
!str.Append( achFlags ) ||
|
||
!msz.Append( str.QueryStr() ))
|
||
{
|
||
return err = GetLastError();
|
||
break;
|
||
}
|
||
|
||
TCP_PRINT(( DBG_CONTEXT,
|
||
"Added \"%s\" from registry as script map\n",
|
||
str.QueryStr() ));
|
||
|
||
fNeedToWrite = TRUE;
|
||
}
|
||
}
|
||
}
|
||
|
||
if ( fNeedToWrite )
|
||
{
|
||
if ( !mb.SetMultiSZ( "",
|
||
MD_SCRIPT_MAPS,
|
||
IIS_MD_UT_FILE,
|
||
msz.QueryStr() ))
|
||
{
|
||
TCP_PRINT(( DBG_CONTEXT,
|
||
"Failed to write MD_SCRIPT_MAPS back to metabase, error %d\n",
|
||
GetLastError() ));
|
||
}
|
||
}
|
||
|
||
RegCloseKey( hkeyParam );
|
||
|
||
return err;
|
||
}
|
||
|
||
VOID
|
||
FreeRegistryExtMap(
|
||
VOID
|
||
)
|
||
{
|
||
if ( !fInitialized )
|
||
{
|
||
return;
|
||
}
|
||
|
||
fInitialized = FALSE;
|
||
}
|
||
|