Leaked source code of windows server 2003
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.
 
 
 
 
 
 

1156 lines
30 KiB

/*++
Copyright (c) 1999 Microsoft Corporation
Module Name :
urlinfo.cxx
Abstract:
Gets metadata for URL
Author:
Bilal Alam (balam) 8-Jan-2000
Environment:
Win32 - User Mode
Project:
ULW3.DLL
--*/
#include "precomp.hxx"
#include <stringau.hxx>
//
// Utility to guard against ~ inconsistency
//
DWORD
CheckIfShortFileName(
IN WCHAR * pszPath,
IN HANDLE hImpersonation,
OUT BOOL * pfShort
);
W3_STATE_URLINFO::W3_STATE_URLINFO()
{
_hr = URL_CONTEXT::Initialize();
}
W3_STATE_URLINFO::~W3_STATE_URLINFO()
{
URL_CONTEXT::Terminate();
}
CONTEXT_STATUS
W3_STATE_URLINFO::OnCompletion(
W3_MAIN_CONTEXT * pMainContext,
DWORD cbCompletion,
DWORD dwCompletionStatus
)
/*++
Routine Description:
Handle URLINFO completions. CheckAccess() is called in DoWork() and this
call is asynchronous.
Arguments:
pMainContext - W3_MAIN_CONTEXT representing execution of state machine
cbCompletion - Number of bytes in an async completion
dwCompletionStatus - Error status of a completion
Return Value:
CONTEXT_STATUS_CONTINUE - if we should continue in state machine
else stop executing the machine and free up the current thread
--*/
{
CONTEXT_STATUS contextStatus;
BOOL fAccessAllowed;
contextStatus = pMainContext->CheckAccess( TRUE, // this is a completion
cbCompletion,
dwCompletionStatus,
&fAccessAllowed );
if ( contextStatus == CONTEXT_STATUS_PENDING )
{
return CONTEXT_STATUS_PENDING;
}
//
// If access is not allowed, then just finish state machine (
// response has already been sent)
//
if ( !fAccessAllowed )
{
pMainContext->SetFinishedResponse();
}
return CONTEXT_STATUS_CONTINUE;
}
CONTEXT_STATUS
W3_STATE_URLINFO::DoWork(
W3_MAIN_CONTEXT * pMainContext,
DWORD cbCompletion,
DWORD dwCompletionStatus
)
/*++
Routine Description:
Handle retrieving the metadata for this request
Arguments:
pMainContext - W3_MAIN_CONTEXT representing execution of state machine
cbCompletion - Number of bytes in an async completion
dwCompletionStatus - Error status of a completion
Return Value:
CONTEXT_STATUS_CONTINUE - if we should continue in state machine
else stop executing the machine and free up the current thread
--*/
{
URL_CONTEXT * pUrlContext = NULL;
BOOL fFinished = FALSE;
HRESULT hr = NO_ERROR;
W3_METADATA * pMetaData = NULL;
CONTEXT_STATUS contextStatus = CONTEXT_STATUS_CONTINUE;
W3_REQUEST * pHttpRequest = pMainContext->QueryRequest();
W3_RESPONSE * pResponse = pMainContext->QueryResponse();
BOOL fAccessAllowed = FALSE;
DBG_ASSERT( pHttpRequest != NULL );
DBG_ASSERT( pResponse != NULL );
//
// Set the context state. Note that passing TRUE as the final
// argument pushes the URL_CONTEXT into the main context. As
// a result, errors in this function should not attempt to
// clean it up.
//
hr = URL_CONTEXT::RetrieveUrlContext( pMainContext,
pMainContext->QueryRequest(),
&pUrlContext,
&fFinished,
TRUE );
if ( FAILED( hr ) )
{
goto Failure;
}
DBG_ASSERT( fFinished || ( pUrlContext != NULL ) );
//
// From now on, errors in this function should not cleanup the URL
// context since it is owned by the main context
//
pUrlContext = NULL;
//
// If filter wants out, leave
//
if ( fFinished )
{
pMainContext->SetDone();
return CONTEXT_STATUS_CONTINUE;
}
//
// Check access now. That means checking for IP/SSL/Certs. We will
// avoid the authentication type check since the others (IP/SSL/Certs)
// take priority.
//
contextStatus = pMainContext->CheckAccess( FALSE, // not a completion
0, // cbCompletion,
NO_ERROR,
&fAccessAllowed );
if ( contextStatus == CONTEXT_STATUS_PENDING )
{
return CONTEXT_STATUS_PENDING;
}
//
// If we don't have access, then the appropriate error response was
// already sent. Just finish the state machine
//
if ( !fAccessAllowed )
{
pMainContext->SetFinishedResponse();
}
return CONTEXT_STATUS_CONTINUE;
Failure:
if ( pUrlContext != NULL )
{
delete pUrlContext;
}
if ( !pMainContext->QueryResponseSent() )
{
if ( hr == HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND ) )
{
// For the non-8dot3 case
pMainContext->QueryResponse()->SetStatus( HttpStatusNotFound );
}
else if ( hr == HRESULT_FROM_WIN32( ERROR_INVALID_DATA ) )
{
pMainContext->QueryResponse()->SetStatus( HttpStatusServerError,
Http500BadMetadata );
}
else if ( hr == HRESULT_FROM_WIN32( ERROR_LOGON_FAILURE ) )
{
pMainContext->QueryResponse()->SetStatus( HttpStatusServerError,
Http500UNCAccess );
}
else
{
pMainContext->QueryResponse()->SetStatus( HttpStatusServerError );
}
}
pMainContext->SetFinishedResponse();
pMainContext->SetErrorStatus( hr );
return CONTEXT_STATUS_CONTINUE;
}
//static
HRESULT
URL_CONTEXT::RetrieveUrlContext(
W3_CONTEXT * pW3Context,
W3_REQUEST * pRequest,
OUT URL_CONTEXT ** ppUrlContext,
BOOL * pfFinished,
BOOL fSetInW3Context
)
/*++
Routine Description:
For a given request, get a URL_CONTEXT which represents the
metadata and URI-specific info for that request
Arguments:
pW3Context - W3_CONTEXT for the request
pRequest - New request to lookup
ppUrlContext - Set to point to new URL_CONTEXT
pfFinished - Set to true if isapi filter said we're finished
fSetInW3Context - OPTIONAL default FALSE
Return Value:
HRESULT
--*/
{
STACK_STRU( strUrl, MAX_PATH );
W3_URL_INFO * pUrlInfo = NULL;
W3_METADATA * pMetaData = NULL;
TOKEN_CACHE_ENTRY * pTokenEntry = NULL;
URL_CONTEXT * pUrlContext = NULL;
HRESULT hr = NO_ERROR;
HANDLE hToken = NULL;
W3_TRACE_LOG * pTraceLog;
if ( pW3Context == NULL ||
pRequest == NULL ||
ppUrlContext == NULL ||
pfFinished == NULL )
{
DBG_ASSERT( FALSE );
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
*ppUrlContext = NULL;
hr = pRequest->GetUrl( &strUrl );
if ( FAILED( hr ) )
{
goto Failure;
}
//
// Lookup the URI info for this request
//
DBG_ASSERT( g_pW3Server->QueryUrlInfoCache() != NULL );
hr = g_pW3Server->QueryUrlInfoCache()->GetUrlInfo(
pW3Context,
strUrl,
&pUrlInfo );
if ( FAILED( hr ) )
{
goto Failure;
}
//
// Now, create a URL_CONTEXT object which contains the W3_URL_INFO and
// W3_METADATA pointers as well as state information for use on cleanup
//
DBG_ASSERT( pUrlInfo != NULL );
pMetaData = (W3_METADATA*) pUrlInfo->QueryMetaData();
DBG_ASSERT( pMetaData != NULL );
pUrlContext = new (pW3Context) URL_CONTEXT( pMetaData, pUrlInfo );
if ( pUrlContext == NULL )
{
hr = HRESULT_FROM_WIN32( ERROR_NOT_ENOUGH_MEMORY );
goto Failure;
}
else if( fSetInW3Context )
{
//
// If specified, set the UrlContext in pW3Context. This is necessary
// since the below filter notification depends on having this context
// for APPL_MD_PATH and APPL_PHYSICAL_PATH. Once set the context owns
// cleaning it up.
//
((W3_MAIN_CONTEXT*)pW3Context)->SetUrlContext( pUrlContext );
}
//
// Now notify URL_MAP filters
//
if ( pW3Context->IsNotificationNeeded( SF_NOTIFY_URL_MAP ) )
{
STACK_STRA( straPhys, MAX_PATH + 1 );
STACK_STRA( straSavePhys, MAX_PATH + 1 );
STACK_STRA( straUrl, MAX_PATH + 1 );
STACK_STRA( straScriptMap, MAX_PATH + 1 );
BOOL fRet;
HTTP_FILTER_URL_MAP_EX filterMap;
STACK_STRU( strPhysicalPath, MAX_PATH );
hr = straPhys.CopyW( pUrlInfo->QueryPhysicalPath()->QueryStr() );
if ( FAILED( hr ) )
{
goto Failure;
}
//
// Save a copy for comparison after filter notification
//
hr = straSavePhys.Copy( straPhys );
if ( FAILED( hr ) )
{
goto Failure;
}
hr = straUrl.CopyW( strUrl.QueryStr() );
if ( FAILED( hr ) )
{
goto Failure;
}
filterMap.pszURL = straUrl.QueryStr();
filterMap.pszPhysicalPath = straPhys.QueryStr();
filterMap.cbPathBuff = straPhys.QuerySize();
filterMap.dwFlags = pMetaData->QueryAccessPerms();
filterMap.cchMatchingPath = pMetaData->QueryCBMatchingPathA();
filterMap.cchMatchingURL = pMetaData->QueryCBMatchingUrlA();
filterMap.pszScriptMapEntry = NULL;
if ( pUrlInfo->QueryScriptMapEntry() )
{
hr = straScriptMap.CopyW( pUrlInfo->QueryScriptMapEntry()->QueryExecutable()->QueryStr() );
if ( FAILED( hr ) )
{
goto Failure;
}
filterMap.pszScriptMapEntry = straScriptMap.QueryStr();
}
fRet = pW3Context->NotifyFilters( SF_NOTIFY_URL_MAP,
&filterMap,
pfFinished );
if ( !fRet )
{
W3_MAIN_CONTEXT * pMainContext = pW3Context->QueryMainContext();
DWORD dwError = GetLastError();
hr = HRESULT_FROM_WIN32( dwError );
pMainContext->SetErrorStatus( hr );
if ( dwError == ERROR_ACCESS_DENIED )
{
pMainContext->QueryResponse()->SetStatus( HttpStatusUnauthorized,
Http401Filter );
}
else if ( dwError == ERROR_FILE_NOT_FOUND ||
dwError == ERROR_PATH_NOT_FOUND )
{
pMainContext->QueryResponse()->SetStatus( HttpStatusNotFound );
}
else
{
pMainContext->QueryResponse()->SetStatus( HttpStatusServerError );
}
goto Failure;
}
//
// If the filter is done, then we're done
//
if ( *pfFinished )
{
hr = NO_ERROR;
goto Failure;
}
//
// If the physical path was changed, remember it here
//
if ( strcmp( straSavePhys.QueryStr(),
filterMap.pszPhysicalPath ) != 0 )
{
hr = strPhysicalPath.CopyA( (CHAR*) filterMap.pszPhysicalPath );
if ( FAILED( hr ) )
{
goto Failure;
}
hr = pUrlContext->SetPhysicalPath( strPhysicalPath );
if ( FAILED( hr ) )
{
goto Failure;
}
}
}
//
// We don't accept short filename since they can break metabase
// equivalency
//
if ( wcschr( pUrlContext->QueryPhysicalPath()->QueryStr(),
L'~' ) )
{
BOOL fShort = FALSE;
hr = pMetaData->GetAndRefVrAccessToken( &pTokenEntry );
if( FAILED( hr ) )
{
goto Failure;
}
if ( pTokenEntry != NULL )
{
hToken = pTokenEntry->QueryImpersonationToken();
}
else
{
hToken = NULL;
}
DWORD dwError = CheckIfShortFileName(
pUrlContext->QueryPhysicalPath()->QueryStr(),
hToken,
&fShort );
if ( dwError != ERROR_SUCCESS )
{
hr = HRESULT_FROM_WIN32( dwError );
goto Failure;
}
if ( fShort )
{
hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
goto Failure;
}
}
//
// Check whether the UNC user was valid. If not, fail
//
if ( pMetaData->QueryUNCUserInvalid() )
{
hr = HRESULT_FROM_WIN32( ERROR_LOGON_FAILURE );
goto Failure;
}
pTraceLog = pW3Context->QueryMainContext()->QueryTraceLog();
if ( pTraceLog != NULL )
{
pTraceLog->Trace( L"%I64x: Successfully metadata for URL '%ws'\n",
pRequest->QueryRequestId(),
strUrl.QueryStr() );
}
*ppUrlContext = pUrlContext;
if( pTokenEntry != NULL )
{
pTokenEntry->DereferenceCacheEntry();
pTokenEntry = NULL;
}
return S_OK;
Failure:
pTraceLog = pW3Context->QueryMainContext()->QueryTraceLog();
if ( pTraceLog != NULL )
{
pTraceLog->Trace( L"%I64x: Failed to retrieve metadata for URL '%ws'. hr = %08X\n",
pRequest->QueryRequestId(),
strUrl.QueryStr(),
hr );
}
if ( pUrlContext != NULL )
{
if( !fSetInW3Context )
{
delete pUrlContext;
}
}
else
{
if ( pUrlInfo != NULL )
{
pUrlInfo->DereferenceCacheEntry();
}
}
if( pTokenEntry != NULL )
{
pTokenEntry->DereferenceCacheEntry();
pTokenEntry = NULL;
}
return hr;
}
//static
HRESULT
W3_STATE_URLINFO::MapPath(
W3_CONTEXT * pW3Context,
STRU & strUrl,
STRU * pstrPhysicalPath,
BOOL fDoFiltering,
DWORD * pcchDirRoot,
DWORD * pcchVRoot,
DWORD * pcbAnsiDirRoot,
DWORD * pcbAnsiVRoot,
DWORD * pdwMask
)
/*++
Routine Description:
Send a URL/Physical-Path pair to a filter for processing
Arguments:
pW3Context - W3_CONTEXT for the request
strUrl - The URL to be mapped
pstrPhysicalPath - Filled with the mapped path upon return. Set with
metadata physical path on entry
fDoFiltering - Enable filters
pcchDirRoot - Set to point to number of characters in found physical path
pcchVRoot - Set to point to number of characters in found virtual path
pcbAnsiDirRoot - Set to point to number of bytes in found ANSI physical path
pcbAnsiVRoot - Set to point to number of bytes in found ANSI virtual path
pdwMask - Set to point to the access perms mask of virtual path
Return Value:
SUCCEEDED()/FAILED()
--*/
{
HRESULT hr = S_OK;
W3_URL_INFO * pUrlInfo = NULL;
W3_METADATA * pMetaData = NULL;
DBG_ASSERT( pstrPhysicalPath );
//
// Get and keep the metadata and urlinfo for this path
//
DBG_ASSERT( g_pW3Server->QueryUrlInfoCache() != NULL );
hr = g_pW3Server->QueryUrlInfoCache()->GetUrlInfo(
pW3Context,
strUrl,
&pUrlInfo );
if ( FAILED( hr ) )
{
goto Exit;
}
DBG_ASSERT( pUrlInfo != NULL );
//
// Call the filters if we should do so
//
if ( fDoFiltering )
{
hr = FilterMapPath( pW3Context,
pUrlInfo,
pstrPhysicalPath );
}
else
{
hr = pstrPhysicalPath->Copy( *( pUrlInfo->QueryUrlTranslated() ) );
}
if ( FAILED( hr ) )
{
goto Exit;
}
pMetaData = pUrlInfo->QueryMetaData();
DBG_ASSERT( pMetaData != NULL );
//
// Return the other goodies
//
if ( pcchDirRoot != NULL )
{
*pcchDirRoot = pMetaData->QueryVrPath()->QueryCCH();
}
if ( pcchVRoot != NULL )
{
if (strUrl.QueryCCH())
{
*pcchVRoot = pMetaData->QueryVrLen();
}
else
{
*pcchVRoot = 0;
}
}
if ( pcbAnsiDirRoot != NULL )
{
*pcbAnsiDirRoot = pMetaData->QueryCBMatchingPathA();
}
if ( pcbAnsiVRoot != NULL )
{
if ( strUrl.QueryCCH() )
{
*pcbAnsiVRoot = pMetaData->QueryCBMatchingUrlA();
}
else
{
*pcbAnsiVRoot = 0;
}
}
if ( pdwMask != NULL )
{
*pdwMask = pMetaData->QueryAccessPerms();
}
Exit:
if ( pUrlInfo != NULL )
{
pUrlInfo->DereferenceCacheEntry();
pUrlInfo = NULL;
}
return hr;
}
// static
HRESULT
W3_STATE_URLINFO::FilterMapPath(
W3_CONTEXT * pW3Context,
W3_URL_INFO * pUrlInfo,
STRU * pstrPhysicalPath
)
/*++
Routine Description:
Have URL_MAP filters do their thing
Arguments:
pW3Context - Context
pUrlInfo - Contains virtual/physical path
pstrPhysicalPath - Filled with physical path
Return Value:
SUCCEEDED()/FAILED()
--*/
{
HRESULT hr = S_OK;
BOOL fFinished = FALSE;
W3_METADATA * pMetaData = NULL;
STACK_STRU( strFilterPath, MAX_PATH );
STRU * pstrFinalPhysical = NULL;
if ( pW3Context == NULL ||
pUrlInfo == NULL ||
pstrPhysicalPath == NULL )
{
DBG_ASSERT( FALSE );
return HRESULT_FROM_WIN32( ERROR_INVALID_PARAMETER );
}
pMetaData = pUrlInfo->QueryMetaData();
DBG_ASSERT( pMetaData != NULL );
//
// We now have the metadata physical path. Let filters change it here
//
if ( pW3Context->IsNotificationNeeded( SF_NOTIFY_URL_MAP ) )
{
STACK_STRA( straPhys, MAX_PATH + 1 );
STACK_STRA( straSavePhys, MAX_PATH + 1 );
STACK_STRA( straUrl, MAX_PATH + 1 );
STACK_STRA( straScriptMap, MAX_PATH + 1 );
BOOL fRet;
HTTP_FILTER_URL_MAP_EX filterMap;
hr = straPhys.CopyW( pUrlInfo->QueryUrlTranslated()->QueryStr() );
if ( FAILED( hr ) )
{
goto Exit;
}
//
// Save a copy for comparison after filter notification
//
hr = straSavePhys.Copy( straPhys );
if ( FAILED( hr ) )
{
goto Exit;
}
hr = straUrl.CopyW( pUrlInfo->QueryUrl() );
if ( FAILED( hr ) )
{
goto Exit;
}
filterMap.pszURL = straUrl.QueryStr();
filterMap.pszPhysicalPath = straPhys.QueryStr();
filterMap.cbPathBuff = straPhys.QuerySize();
filterMap.dwFlags = pMetaData->QueryAccessPerms();
filterMap.cchMatchingPath = pMetaData->QueryCBMatchingPathA();
filterMap.cchMatchingURL = pMetaData->QueryCBMatchingUrlA();
filterMap.pszScriptMapEntry = NULL;
if ( pUrlInfo->QueryScriptMapEntry() )
{
hr = straScriptMap.CopyW( pUrlInfo->QueryScriptMapEntry()->QueryExecutable()->QueryStr() );
if ( FAILED( hr ) )
{
goto Exit;
}
filterMap.pszScriptMapEntry = straScriptMap.QueryStr();
}
fRet = pW3Context->NotifyFilters( SF_NOTIFY_URL_MAP,
&filterMap,
&fFinished );
//
// Ignore finished flag in this case since we really can't do much
// to advance to finish (since an ISAPI is calling this)
//
if ( !fRet )
{
hr = HRESULT_FROM_WIN32( GetLastError() );
goto Exit;
}
//
// Remember the mapped path
//
if ( strcmp( straSavePhys.QueryStr(),
filterMap.pszPhysicalPath ) != 0 )
{
hr = strFilterPath.CopyA( (CHAR*) filterMap.pszPhysicalPath );
if ( FAILED( hr ) )
{
goto Exit;
}
pstrFinalPhysical = &strFilterPath;
}
else
{
pstrFinalPhysical = pUrlInfo->QueryUrlTranslated();
}
}
else
{
//
// No filter is mapping, therefore just take the URL_INFO's physical
// path
//
pstrFinalPhysical = pUrlInfo->QueryUrlTranslated();
DBG_ASSERT( pstrFinalPhysical != NULL );
}
//
// We don't accept short filename since they can break metabase
// equivalency
//
if ( wcschr( pstrFinalPhysical->QueryStr(),
L'~' ) )
{
BOOL fShort = FALSE;
DWORD dwError = CheckIfShortFileName(
pstrFinalPhysical->QueryStr(),
pW3Context->QueryImpersonationToken(),
&fShort );
if ( dwError != ERROR_SUCCESS )
{
hr = HRESULT_FROM_WIN32( dwError );
goto Exit;
}
if ( fShort )
{
hr = HRESULT_FROM_WIN32( ERROR_FILE_NOT_FOUND );
goto Exit;
}
}
//
// Copy the physical path is requested
//
hr = pstrPhysicalPath->Copy( *pstrFinalPhysical );
if ( FAILED( hr ) )
{
goto Exit;
}
Exit:
return hr;
}
DWORD
CheckIfShortFileName(
IN WCHAR * pszPath,
IN HANDLE hImpersonation,
OUT BOOL * pfShort
)
/*++
Description:
This function takes a suspected NT/Win95 short filename and checks if there's
an equivalent long filename. For example, c:\foobar\ABCDEF~1.ABC is the same
as c:\foobar\abcdefghijklmnop.abc.
NOTE: This function should be called unimpersonated - the FindFirstFile() must
be called in the system context since most systems have traverse checking turned
off - except for the UNC case where we must be impersonated to get network access.
Arguments:
pszPath - Path to check
hImpersonation - Impersonation handle if this is a UNC path - can be NULL if not UNC
pfShort - Set to TRUE if an equivalent long filename is found
Returns:
Win32 error on failure
--*/
{
DWORD err = NO_ERROR;
WIN32_FIND_DATA FindData;
WCHAR * psz;
BOOL fUNC;
psz = wcschr( pszPath, L'~' );
*pfShort = FALSE;
fUNC = (*pszPath == L'\\');
//
// Loop for multiple tildas - watch for a # after the tilda
//
while ( psz++ )
{
if ( *psz >= L'0' && *psz <= L'9' )
{
WCHAR achTmp[MAX_PATH];
WCHAR * pchEndSeg;
WCHAR * pchBeginSeg;
HANDLE hFind;
//
// Isolate the path up to the segment with the
// '~' and do the FindFirst with that path
//
pchEndSeg = wcschr( psz, L'\\' );
if ( !pchEndSeg )
{
pchEndSeg = psz + wcslen( psz );
}
//
// If the string is beyond MAX_PATH then we allow it through
//
if ( ((INT) (pchEndSeg - pszPath)) >= MAX_PATH )
{
return NO_ERROR;
}
memcpy( achTmp,
pszPath,
(INT) (pchEndSeg - pszPath) * sizeof( WCHAR ) );
achTmp[pchEndSeg - pszPath] = L'\0';
if ( fUNC && hImpersonation )
{
if ( !SetThreadToken( NULL, hImpersonation ))
{
return GetLastError();
}
}
//
// IVANPASH: Although it looks simpler to use GetLongPathName
// instead of manually traversing the folders, we must use
// FindFirstFileW, because GetLongPathName requires ACLs for
// IIS_WPG from the root of the drive to work.
//
hFind = FindFirstFileW( achTmp, &FindData );
if ( fUNC && hImpersonation )
{
RevertToSelf();
}
if ( hFind == INVALID_HANDLE_VALUE )
{
err = GetLastError();
DBGPRINTF(( DBG_CONTEXT,
"FindFirst failed!! - \"%s\", error %d\n",
achTmp,
GetLastError() ));
//
// If the FindFirstFile() fails to find the file then return
// success - the path doesn't appear to be a valid path which
// is ok.
//
if ( err == ERROR_FILE_NOT_FOUND ||
err == ERROR_PATH_NOT_FOUND ||
err == ERROR_INVALID_NAME )
{
return NO_ERROR;
}
return err;
}
DBG_REQUIRE( FindClose( hFind ));
//
// Isolate the last segment of the string which should be
// the potential short name equivalency
//
pchBeginSeg = wcsrchr( achTmp, L'\\' );
DBG_ASSERT( pchBeginSeg );
pchBeginSeg++;
//
// If the last segment doesn't match the long name then this is
// the short name version of the path
//
if ( _wcsicmp( FindData.cFileName, pchBeginSeg ))
{
*pfShort = TRUE;
return NO_ERROR;
}
}
psz = wcschr( psz, L'~' );
}
return err;
}
HRESULT
URL_CONTEXT::OpenFile(
CACHE_USER * pFileUser,
W3_FILE_INFO ** ppOpenFile,
FILE_CACHE_ASYNC_CONTEXT * pAsyncContext,
BOOL * pfHandledSync,
BOOL fAllowNoBuffering,
BOOL fCheckForExistenceOnly
)
/*++
Routine Description:
Open the physical path for this request. If a map path filter did some
redirecting, we will use that path. Otherwise we will just use the
path determined by metadata and cached in the W3_URL_INFO
Arguments:
pFileUser - User to open file as
ppOpenFile - Set to file cache entry on success
pAsyncContext - In case an async read is desired, context with callback information
pfHandledSync - Did the open complete synchronously
fAllowNoBuffering - Allow the file to be opened with FILE_FLAG_NO_BUFFERING
fCheckForExistenceOnly - Only interested in existence of the file
Return Value:
HRESULT
--*/
{
HRESULT hr;
BOOL fDoCache;
DBG_ASSERT( QueryMetaData() != NULL );
fDoCache = !QueryMetaData()->QueryNoCache();
//
// If an ISAPI filter changed the physical path, then we need to go
// directly to the file cache. Otherwise, we can go thru the
// W3_URL_INFO which may already have the cached file associated
//
if ( _strPhysicalPath.IsEmpty() )
{
//
// No filter. Fast path :-)
//
DBG_ASSERT( _pUrlInfo != NULL );
hr = _pUrlInfo->GetFileInfo( pFileUser,
fDoCache,
ppOpenFile,
pAsyncContext,
pfHandledSync,
fAllowNoBuffering,
fCheckForExistenceOnly );
}
else
{
//
// Filter case. Must lookup in file cache :-(
//
DBG_ASSERT( g_pW3Server->QueryFileCache() != NULL );
hr = g_pW3Server->QueryFileCache()->GetFileInfo(
_strPhysicalPath,
QueryMetaData()->QueryDirmonConfig(),
pFileUser,
fDoCache,
ppOpenFile,
pAsyncContext,
pfHandledSync,
fAllowNoBuffering,
fCheckForExistenceOnly );
}
return hr;
}
//static
HRESULT
URL_CONTEXT::Initialize(
VOID
)
/*++
Routine Description:
Initialize URL_CONTEXT lookaside
Arguments:
None
Return Value:
HRESULT
--*/
{
return NO_ERROR;
}
//static
VOID
URL_CONTEXT::Terminate(
VOID
)
/*++
Routine Description:
Clean up URL_CONTEXT lookaside
Arguments:
None
Return Value:
HRESULT
--*/
{
}