windows-nt/Source/XPSP1/NT/inetsrv/iis/svcs/cmp/asp/server.cpp
2020-09-26 16:20:57 +08:00

1129 lines
27 KiB
C++

/*===================================================================
Microsoft Denali
Microsoft Confidential.
Copyright 1996 Microsoft Corporation. All Rights Reserved.
Component: Server object
File: Server.cpp
Owner: CGrant
This file contains the code for the implementation of the Server object.
===================================================================*/
#include "denpre.h"
#pragma hdrstop
#include "Server.h"
#include "tlbcache.h"
#include "memchk.h"
/*
*
* C S e r v e r
*
*/
/*===================================================================
CServer::CServer
Constructor
Parameters:
punkOuter object to ref count (can be NULL)
Returns:
===================================================================*/
CServer::CServer(IUnknown *punkOuter)
:
m_fInited(FALSE),
m_fDiagnostics(FALSE),
m_pData(NULL)
{
CDispatch::Init(IID_IServer);
if (punkOuter)
{
m_punkOuter = punkOuter;
m_fOuterUnknown = TRUE;
}
else
{
m_cRefs = 1;
m_fOuterUnknown = FALSE;
}
#ifdef DBG
m_fDiagnostics = TRUE;
#endif // DBG
}
/*===================================================================
CServer::~CServer
Destructor
Parameters:
Returns:
===================================================================*/
CServer::~CServer()
{
Assert(!m_fInited);
Assert(m_fOuterUnknown || m_cRefs == 0); // must have 0 ref count
}
/*===================================================================
CServer::Init
Allocates m_pData.
Performs any intiailization of a CServer that's prone to failure
that we also use internally before exposing the object outside.
Parameters:
None
Returns:
S_OK on success.
===================================================================*/
HRESULT CServer::Init()
{
if (m_fInited)
return S_OK; // already inited
Assert(!m_pData);
m_pData = new CServerData;
if (!m_pData)
return E_OUTOFMEMORY;
m_pData->m_pIReq = NULL;
m_pData->m_pHitObj = NULL;
m_pData->m_ISupportErrImp.Init(static_cast<IServer *>(this),
static_cast<IServer *>(this),
IID_IServer);
m_fInited = TRUE;
return S_OK;
}
/*===================================================================
CServer::UnInit
Remove m_pData. Make tombstone (UnInited state).
Parameters:
Returns:
HRESULT (S_OK)
===================================================================*/
HRESULT CServer::UnInit()
{
if (!m_fInited)
return S_OK; // already uninited
Assert(m_pData);
delete m_pData;
m_pData = NULL;
m_fInited = FALSE;
return S_OK;
}
/*===================================================================
CServer::ReInit
The only need for a re-init here is to update the CIsapiReqInfo
for this request, the CIsapiReqInfo is required to access the
MapPath Method. Ideally this method should be part of the Request
object
Parameters:
CIsapiReqInfo *
CHitObj *
Returns:
S_OK on success.
===================================================================*/
HRESULT CServer::ReInit
(
CIsapiReqInfo * pIReq,
CHitObj *pHitObj
)
{
Assert(m_fInited);
Assert(m_pData);
m_pData->m_pIReq = pIReq;
m_pData->m_pHitObj = pHitObj;
return S_OK;
}
/*===================================================================
CServer::MapPathInternal
Map virtual path BSTR into single char buffer
Used by MapPath(), Execute(), Transfer()
Parameters:
dwContextId for error messages
wszVirtPath path to translate
szPhysPath [out] translate into this buffer (MAX_PATH sized)
szVirtPath [out, optional] mb virtual path buffer (MAX_PATH sized)
Returns:
S_OK on success.
===================================================================*/
HRESULT CServer::MapPathInternal
(
DWORD dwContextId,
WCHAR *wszVirtPath,
TCHAR *szPhysPath,
TCHAR *szVirtPath
)
{
// increment the pointer past leading white spaces
wchar_t *wszLogicalPath = wszVirtPath;
while (iswspace(*wszLogicalPath))
++wszLogicalPath;
unsigned cchLogicalPath = wcslen(wszLogicalPath);
if (cchLogicalPath > MAX_PATH-1)
{
if (dwContextId)
ExceptionId(IID_IServer, dwContextId, IDE_SERVER_EXCEDED_MAX_PATH);
return E_FAIL;
}
else if (cchLogicalPath == 0)
{
if (dwContextId)
ExceptionId(IID_IServer, dwContextId, IDE_SERVER_MAPPATH_INVALID_STR);
return E_FAIL;
}
// Is this a physical path?
if (iswalpha(wszLogicalPath[0]) && wszLogicalPath[1] == L':')
{
if (dwContextId)
ExceptionId(IID_IServer, dwContextId, IDE_SERVER_MAPPATH_PHY_STR);
return E_FAIL;
}
// simple validation: look for invalid characters in string [*?<>,;:'"]
// and multiple slash characters ie "//" or "\\"
//
BOOL fParentPath = FALSE;
BOOL fEnableParentPaths = m_pData->m_pHitObj->QueryAppConfig()->fEnableParentPaths();
BOOL fAnyBackslashes = FALSE;
wchar_t *pwchT = wszLogicalPath;
while (*pwchT != L'\0')
{
switch (*pwchT)
{
case L'*': case L':': case L'?': case L'<':
case L'>': case L',': case L'"':
if (dwContextId)
ExceptionId( IID_IServer, dwContextId, IDE_SERVER_MAPPATH_INVALID_CHR);
return E_FAIL;
case L'.':
if (*++pwchT == L'.')
{
if (!fEnableParentPaths)
{
if (dwContextId)
ExceptionId(IID_IServer, dwContextId, IDE_SERVER_MAPPATH_INVALID_CHR3);
return E_FAIL;
}
else
{
fParentPath = TRUE;
++pwchT;
}
}
break;
case L'\\':
fAnyBackslashes = TRUE;
case L'/':
++pwchT;
if (*pwchT == '/' || *pwchT == '\\')
{
if (dwContextId)
ExceptionId(IID_IServer, dwContextId, IDE_SERVER_MAPPATH_INVALID_CHR2);
return E_FAIL;
}
break;
default:
++pwchT;
}
}
// whew! Error handling done!
// Convert wszLogicalPath to multi-byte
TCHAR szLogicalPath[MAX_PATH];
#if UNICODE
wcscpy(szLogicalPath, wszLogicalPath);
#else
HRESULT hr;
CWCharToMBCS convStr;
if (hr = convStr.Init(wszLogicalPath)) {
if ((hr == E_OUTOFMEMORY) && dwContextId)
ExceptionId(IID_IServer, dwContextId, IDE_OOM);
return hr;
}
if (convStr.GetStringLen() > (MAX_PATH-1)) {
if (dwContextId)
ExceptionId(IID_IServer, dwContextId, IDE_SERVER_EXCEDED_MAX_PATH);
return E_FAIL;
}
strcpy(szLogicalPath,convStr.GetString());
#endif
// change all backslashes to forward slashes
if (fAnyBackslashes)
{
TCHAR *pbBackslash = szLogicalPath;
while (pbBackslash = _tcschr(pbBackslash, _T('\\')))
*pbBackslash = _T('/');
}
// is this a Relative path request. I.E. no leading slash
// if so prepend the path_info string to szLogicalPath
BOOL fPathAlreadyIsMapped = FALSE; // Some cases map the path earlier
if (szLogicalPath[0] != _T('/'))
{
TCHAR szParentPath[MAX_PATH];
_tcscpy(szParentPath, m_pData->m_pIReq->QueryPszPathInfo());
// Trim off the ASP file name from the PATH_INFO
TCHAR *pchT = _tcsrchr(szParentPath, _T('/'));
if (pchT != NULL) *pchT = '\0';
// If there were parent paths, map the parent now, then append the relative path
// the relative path to the parent path
if (fParentPath)
{
Assert (fEnableParentPaths); // Errors should have been flagged upstairs
DWORD dwPathSize = sizeof(szParentPath);
if (! m_pData->m_pIReq->MapUrlToPath(szParentPath, &dwPathSize))
{
if (dwContextId)
ExceptionId(IID_IServer,
dwContextId,
::GetLastError() == ERROR_INSUFFICIENT_BUFFER? IDE_SERVER_EXCEDED_MAX_PATH : IDE_SERVER_MAPPATH_FAILED);
return E_FAIL;
}
fPathAlreadyIsMapped = TRUE;
}
// Resolve relative paths
if (! DotPathToPath(szLogicalPath, szLogicalPath, szParentPath))
{
if (dwContextId)
ExceptionId(IID_IServer, dwContextId, IDE_SERVER_MAPPATH_FAILED);
return E_FAIL;
}
}
// return virtual path if requested
if (szVirtPath)
_tcscpy(szVirtPath, szLogicalPath);
// Map this to a physical file name (if required)
if (!fPathAlreadyIsMapped)
{
DWORD dwPathSize = sizeof(szLogicalPath);
if (! m_pData->m_pIReq->MapUrlToPath(szLogicalPath, &dwPathSize))
{
if (dwContextId)
ExceptionId(IID_IServer,
dwContextId,
::GetLastError() == ERROR_INSUFFICIENT_BUFFER? IDE_SERVER_EXCEDED_MAX_PATH : IDE_SERVER_MAPPATH_FAILED);
return E_FAIL;
}
}
// remove any ending delimiters (unless it's the root directory. The root always starts with drive letter)
TCHAR *pchT = CharPrev(szLogicalPath, szLogicalPath + _tcslen(szLogicalPath));
if ((*pchT == _T('/') || *pchT == _T('\\')) && pchT[-1] != _T(':'))
{
*pchT = _T('\0');
}
// Replace forward slash with back slash
for (pchT = szLogicalPath; *pchT != _T('\0'); ++pchT)
{
if (*pchT == _T('/'))
*pchT = _T('\\');
}
_tcscpy(szPhysPath, szLogicalPath);
return S_OK;
}
/*===================================================================
CServer::QueryInterface
CServer::AddRef
CServer::Release
IUnknown members for CServer object.
===================================================================*/
STDMETHODIMP CServer::QueryInterface
(
REFIID riid,
PPVOID ppv
)
{
*ppv = NULL;
/*
* The only calls for IUnknown are either in a nonaggregated
* case or when created in an aggregation, so in either case
* always return our IUnknown for IID_IUnknown.
*/
// BUG FIX 683 added IID_IDenaliIntrinsic to prevent the user from
// storing intrinsic objects in the application and session object
if (IID_IUnknown == riid ||
IID_IDispatch == riid ||
IID_IServer == riid ||
IID_IDenaliIntrinsic == riid)
*ppv = static_cast<IServer *>(this);
//Indicate that we support error information
if (IID_ISupportErrorInfo == riid)
{
if (m_pData)
*ppv = & (m_pData->m_ISupportErrImp);
}
if (IID_IMarshal == riid)
{
*ppv = static_cast<IMarshal *>(this);
}
//AddRef any interface we'll return.
if (NULL != *ppv)
{
((LPUNKNOWN)*ppv)->AddRef();
return S_OK;
}
return E_NOINTERFACE;
}
STDMETHODIMP_(ULONG) CServer::AddRef()
{
if (m_fOuterUnknown)
return m_punkOuter->AddRef();
return InterlockedIncrement((LPLONG)&m_cRefs);
}
STDMETHODIMP_(ULONG) CServer::Release()
{
if (m_fOuterUnknown)
return m_punkOuter->Release();
DWORD cRefs = InterlockedDecrement((LPLONG)&m_cRefs);
if (cRefs)
return cRefs;
delete this;
return 0;
}
/*===================================================================
CServer::GetIDsOfNames
Special-case implementation for CreateObject, Execute, Transfer
Parameters:
riid REFIID reserved. Must be IID_NULL.
rgszNames OLECHAR ** pointing to the array of names to be mapped.
cNames UINT number of names to be mapped.
lcid LCID of the locale.
rgDispID DISPID * caller allocated array containing IDs
corresponging to those names in rgszNames.
Return Value:
HRESULT S_OK or a general error code.
===================================================================*/
STDMETHODIMP CServer::GetIDsOfNames
(
REFIID riid,
OLECHAR **rgszNames,
UINT cNames,
LCID lcid,
DISPID *rgDispID
)
{
const DISPID dispidCreateObject = 0x60020002;
const DISPID dispidExecute = 0x60020007;
const DISPID dispidTransfer = 0x60020008;
if (cNames == 1)
{
switch (rgszNames[0][0])
{
case L'C':
case L'c':
if (wcsicmp(rgszNames[0]+1, L"reateobject") == 0)
{
*rgDispID = dispidCreateObject;
return S_OK;
}
break;
case L'E':
case L'e':
if (wcsicmp(rgszNames[0]+1, L"xecute") == 0)
{
*rgDispID = dispidExecute;
return S_OK;
}
break;
case L'T':
case L't':
if (wcsicmp(rgszNames[0]+1, L"ransfer") == 0)
{
*rgDispID = dispidTransfer;
return S_OK;
}
break;
}
}
// default to CDispatch's implementation
return CDispatch::GetIDsOfNames(riid, rgszNames, cNames, lcid, rgDispID);
}
/*===================================================================
CServer::CheckForTombstone
Tombstone stub for IServer methods. If the object is
tombstone, does ExceptionId and fails.
Parameters:
Returns:
HRESULT E_FAIL if Tombstone
S_OK if not
===================================================================*/
HRESULT CServer::CheckForTombstone()
{
if (m_fInited)
{
// inited - good object
Assert(m_pData); // must be present for inited objects
return S_OK;
}
ExceptionId
(
IID_IServer,
IDE_SERVER,
IDE_INTRINSIC_OUT_OF_SCOPE
);
return E_FAIL;
}
/*===================================================================
CServer::CreateObject
Parameters: BSTR containing ProgID
Variant to fillin with IUknown pointer
Returns: S_OK if successful E_FAIL otherwise
Side effects:
Creates an instance of an ole automation object
===================================================================*/
STDMETHODIMP CServer::CreateObject(BSTR bstrProgID, IDispatch **ppDispObj)
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
if (bstrProgID == NULL)
{
ExceptionId(IID_IServer, IDE_SERVER, IDE_EXPECTING_STR);
return E_FAIL;
}
Assert(m_pData->m_pHitObj);
*ppDispObj = NULL;
HRESULT hr;
CLSID clsid;
if (Glob(fEnableTypelibCache))
{
// Use typelib cache to create the component
hr = g_TypelibCache.CreateComponent
(
bstrProgID,
m_pData->m_pHitObj,
ppDispObj,
&clsid
);
if (FAILED(hr) && clsid == CLSID_NULL)
{
// bad prog id or something
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_CREATEOBJ_FAILED, hr);
return hr;
}
}
else
{
// Don't use typelib cache
hr = CLSIDFromProgID((LPCOLESTR)bstrProgID, &clsid);
if (FAILED(hr))
{
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_CREATEOBJ_FAILED, hr);
return hr;
}
hr = m_pData->m_pHitObj->CreateComponent(clsid, ppDispObj);
}
if (SUCCEEDED(hr))
return S_OK;
// Check if a custom error was already posted
IErrorInfo *pErrInfo = NULL;
if (GetErrorInfo(0, &pErrInfo) == S_OK && pErrInfo)
{
SetErrorInfo(0, pErrInfo);
pErrInfo->Release();
}
// Standard errors
else if (hr == E_ACCESSDENIED)
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_CREATEOBJ_DENIED);
else
{
if (hr == REGDB_E_CLASSNOTREG)
{
BOOL fInProc;
if (SUCCEEDED(CompModelFromCLSID(clsid, NULL, &fInProc)) && !fInProc)
{
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_CREATEOBJ_NOTINPROC);
}
}
else
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_CREATEOBJ_FAILED, hr);
}
return hr;
}
/*===================================================================
CServer::MapPath
Return the physical path translated from a logical path
Parameters:
BSTR bstrLogicalPath
BSTR FAR * pbstrPhysicalPath
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::MapPath(BSTR bstrLogicalPath, BSTR FAR * pbstrPhysicalPath)
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
// Bug 1361: error if no CIsapiReqInfo (presumably called during
// Application_OnEnd or Session_OnEnd)
if (m_pData->m_pIReq == NULL)
{
ExceptionId(IID_IServer, IDE_SERVER_MAPPATH, IDE_SERVER_INVALID_CALL);
return E_FAIL;
}
AssertValid();
Assert (pbstrPhysicalPath != NULL);
*pbstrPhysicalPath = NULL;
// use MapPathInternal() to do the mapping
TCHAR szLogicalPath[MAX_PATH];
HRESULT hr = MapPathInternal(IDE_SERVER_MAPPATH, bstrLogicalPath, szLogicalPath);
if (FAILED(hr))
return hr;
#if UNICODE
*pbstrPhysicalPath = SysAllocString(szLogicalPath);
if (*pbstrPhysicalPath == NULL) {
ExceptionId(IID_IServer, IDE_SERVER_MAPPATH, IDE_OOM);
return E_FAIL;
}
#else
// Convert the path to wide character
if (FAILED(SysAllocStringFromSz(szLogicalPath, 0, pbstrPhysicalPath, CP_ACP))) {
ExceptionId(IID_IServer, IDE_SERVER_MAPPATH, IDE_OOM);
return E_FAIL;
}
#endif
return S_OK;
}
/*===================================================================
CServer::HTMLEncode
Encodes a string to HTML standards
Parameters:
BSTR bstrIn value: string to be encoded
BSTR FAR * pbstrEncoded value: pointer to HTML encoded version of string
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::HTMLEncode ( BSTR bstrIn, BSTR FAR * pbstrEncoded )
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
char* pszstrIn = NULL;
char* pszEncodedstr = NULL;
char* pszStartEncodestr = NULL;
int nbstrLen = 0;
int nstrLen = 0;
HRESULT hr = S_OK;
UINT uCodePage = m_pData->m_pHitObj->GetCodePage();
CWCharToMBCS convIn;
STACK_BUFFER( tempHTML, 2048 );
if (bstrIn)
nbstrLen = wcslen(bstrIn);
else
nbstrLen = 0;
if (nbstrLen <= 0)
return S_OK;
if (FAILED(hr = convIn.Init(bstrIn, uCodePage))) {
if (hr == E_OUTOFMEMORY)
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
goto L_Exit;
}
pszstrIn = convIn.GetString();
nstrLen = HTMLEncodeLen(pszstrIn, uCodePage, bstrIn);
if (nstrLen > 0)
{
//Encode string , NOTE this function returns a pointer to the
// NULL so you need to keep a pointer to the start of the string
//
if (!tempHTML.Resize(nstrLen + 2)) {
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
hr = E_FAIL;
goto L_Exit;
}
pszEncodedstr = (char*)tempHTML.QueryPtr();
pszStartEncodestr = pszEncodedstr;
pszEncodedstr = ::HTMLEncode( pszEncodedstr, pszstrIn, uCodePage, bstrIn);
// convert result to bstr
//
if (FAILED(SysAllocStringFromSz(pszStartEncodestr, 0, pbstrEncoded, uCodePage)))
{
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
hr = E_FAIL;
goto L_Exit;
}
}
L_Exit:
return hr;
}
/*===================================================================
CServer::URLEncode
Encodes a query string to URL standards
Parameters:
BSTR bstrIn value: string to be URL encoded
BSTR FAR * pbstrEncoded value: pointer to URL encoded version of string
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::URLEncode ( BSTR bstrIn, BSTR FAR * pbstrEncoded )
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
char* pszstrIn = NULL;
char* pszEncodedstr = NULL;
char* pszStartEncodestr = NULL;
int nbstrLen = 0;
int nstrLen = 0;
HRESULT hr = S_OK;
CWCharToMBCS convIn;
STACK_BUFFER( tempURL, 256 );
if (bstrIn)
nbstrLen = wcslen(bstrIn);
else
nbstrLen = 0;
if (nbstrLen <= 0)
return S_OK;
if (FAILED(hr = convIn.Init(bstrIn, m_pData->m_pHitObj->GetCodePage()))) {
if (hr == E_OUTOFMEMORY)
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
goto L_Exit;
}
pszstrIn = convIn.GetString();
nstrLen = URLEncodeLen(pszstrIn);
if (nstrLen > 0)
{
//Encode string , NOTE this function returns a pointer to the
// NULL so you need to keep a pointer to the start of the string
//
if (!tempURL.Resize(nstrLen + 2)) {
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
hr = E_FAIL;
goto L_Exit;
}
pszEncodedstr = (char *)tempURL.QueryPtr();
pszStartEncodestr = pszEncodedstr;
pszEncodedstr = ::URLEncode( pszEncodedstr, pszstrIn );
// convert result to bstr
//
if (FAILED(SysAllocStringFromSz(pszStartEncodestr, 0, pbstrEncoded)))
{
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
hr = E_FAIL;
goto L_Exit;
}
}
L_Exit:
return hr;
}
/*===================================================================
CServer::URLPathEncode
Encodes the path portion of a URL or a full URL. All characters
up to the first '?' are encoded with the following rules:
o Charcters that are needed to parse the URL are left alone
o RFC 1630 safe characters are left alone
o Non-foreign alphanumberic characters are left alone
o Anything else is escape encoded
Everything after the '?' is not encoded.
Parameters:
BSTR bstrIn value: string to be URL path encoded
BSTR FAR * pbstrEncoded value: pointer to URL path encoded version of string
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::URLPathEncode ( BSTR bstrIn, BSTR FAR * pbstrEncoded )
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
char* pszstrIn = NULL;
char* pszEncodedstr = NULL;
char* pszStartEncodestr = NULL;
int nbstrLen = 0;
int nstrLen = 0;
HRESULT hr = S_OK;
CWCharToMBCS convIn;
STACK_BUFFER( tempPath, 256 );
if (bstrIn)
nbstrLen = wcslen(bstrIn);
else
nbstrLen = 0;
if (nbstrLen <= 0)
return S_OK;
if (FAILED(hr = convIn.Init(bstrIn, m_pData->m_pHitObj->GetCodePage()))) {
if (hr == E_OUTOFMEMORY)
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
goto L_Exit;
}
pszstrIn = convIn.GetString();
nstrLen = URLPathEncodeLen(pszstrIn);
if (nstrLen > 0)
{
//Encode string , NOTE this function returns a pointer to the
// NULL so you need to keep a pointer to the start of the string
//
if (!tempPath.Resize(nstrLen+2)) {
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
hr = E_FAIL;
goto L_Exit;
}
pszEncodedstr = (char *)tempPath.QueryPtr();
pszStartEncodestr = pszEncodedstr;
pszEncodedstr = ::URLPathEncode( pszEncodedstr, pszstrIn );
// convert result to bstr
//
if (FAILED(SysAllocStringFromSz(pszStartEncodestr, 0, pbstrEncoded)))
{
ExceptionId( IID_IServer, IDE_SERVER, IDE_OOM);
hr = E_FAIL;
goto L_Exit;
}
}
L_Exit:
return hr;
}
/*===================================================================
CServer::get_ScriptTimeout
Will return the script timeout interval (in seconds)
Parameters:
long *plTimeoutSeconds
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::get_ScriptTimeout( long * plTimeoutSeconds )
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
if (m_pData->m_pHitObj == NULL)
{
ExceptionId(IID_IServer, IDE_SERVER_MAPPATH, IDE_SERVER_INVALID_CALL);
return(E_FAIL);
}
*plTimeoutSeconds = m_pData->m_pHitObj->GetScriptTimeout();
return S_OK;
}
/*===================================================================
CServer::put_ScriptTimeout
Allows the user to set the timeout interval for a script (in seconds)
Parameters:
long lTimeoutSeconds
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::put_ScriptTimeout( long lTimeoutSeconds )
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
if ( lTimeoutSeconds < 0 )
{
ExceptionId( IID_IServer, IDE_SERVER, IDE_SERVER_INVALID_TIMEOUT );
return E_FAIL;
}
else
{
if (m_pData->m_pHitObj == NULL)
{
ExceptionId(IID_IServer, IDE_SERVER_MAPPATH, IDE_SERVER_INVALID_CALL);
return(E_FAIL);
}
m_pData->m_pHitObj->SetScriptTimeout(lTimeoutSeconds);
return S_OK;
}
}
/*===================================================================
CServer::Execute
Execute an ASP
Parameters:
bstrURL URL to execute
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::Execute(BSTR bstrURL)
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
if (m_pData->m_pIReq == NULL || m_pData->m_pHitObj == NULL)
{
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_INVALID_CALL);
return E_FAIL;
}
TCHAR szTemplate[MAX_PATH], szVirtTemp[MAX_PATH];
HRESULT hr = MapPathInternal(IDE_SERVER, bstrURL, szTemplate, szVirtTemp);
if (FAILED(hr))
{
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_EXECUTE_INVALID_PATH);
return hr;
}
Normalize(szTemplate);
hr = m_pData->m_pHitObj->ExecuteChildRequest(FALSE, szTemplate, szVirtTemp);
if (FAILED(hr))
{
if (m_pData->m_pHitObj->FHasASPError()) // error already reported
return hr;
ExceptionId(IID_IServer, IDE_SERVER, (hr == E_COULDNT_OPEN_SOURCE_FILE) ?
IDE_SERVER_EXECUTE_CANTLOAD : IDE_SERVER_EXECUTE_FAILED);
return E_FAIL;
}
return S_OK;
}
/*===================================================================
CServer::Transfer
Transfer execution an ASP
Parameters:
bstrURL URL to execute
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::Transfer(BSTR bstrURL)
{
if (FAILED(CheckForTombstone()))
return E_FAIL;
if (m_pData->m_pIReq == NULL || m_pData->m_pHitObj == NULL)
{
ExceptionId(IID_IServer, IDE_SERVER_MAPPATH, IDE_SERVER_INVALID_CALL);
return E_FAIL;
}
TCHAR szTemplate[MAX_PATH], szVirtTemp[MAX_PATH];
HRESULT hr = MapPathInternal(IDE_SERVER, bstrURL, szTemplate, szVirtTemp);
if (FAILED(hr))
{
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_TRANSFER_INVALID_PATH);
return hr;
}
Normalize(szTemplate);
hr = m_pData->m_pHitObj->ExecuteChildRequest(TRUE, szTemplate, szVirtTemp);
if (FAILED(hr))
{
if (m_pData->m_pHitObj->FHasASPError()) // error already reported
return hr;
ExceptionId(IID_IServer, IDE_SERVER, (hr == E_COULDNT_OPEN_SOURCE_FILE) ?
IDE_SERVER_TRANSFER_CANTLOAD : IDE_SERVER_TRANSFER_FAILED);
return E_FAIL;
}
return S_OK;
}
/*===================================================================
CServer::GetLastError
Get ASPError object for the last error
Parameters:
ppASPErrorObject [out] the error object
Returns:
HRESULT S_OK on success
===================================================================*/
STDMETHODIMP CServer::GetLastError(IASPError **ppASPErrorObject)
{
*ppASPErrorObject = NULL;
if (FAILED(CheckForTombstone()))
return E_FAIL;
if (m_pData->m_pIReq == NULL || m_pData->m_pHitObj == NULL)
{
ExceptionId(IID_IServer, IDE_SERVER, IDE_SERVER_INVALID_CALL);
return E_FAIL;
}
HRESULT hr = m_pData->m_pHitObj->GetASPError(ppASPErrorObject);
if (FAILED(hr))
{
ExceptionId(IID_IServer, IDE_SERVER, IDE_UNEXPECTED);
return hr;
}
return S_OK;
}
#ifdef DBG
/*===================================================================
CServer::AssertValid
Test to make sure that the CServer object is currently correctly formed
and assert if it is not.
Returns:
Side effects:
None.
===================================================================*/
void CServer::AssertValid() const
{
Assert(m_fInited);
Assert(m_pData);
Assert(m_pData->m_pIReq);
}
#endif DBG