// This is a part of the Active Template Library.
// Copyright (C) Microsoft Corporation
// All rights reserved.
//
// This source code is only intended as a supplement to the
// Active Template Library Reference and related
// electronic documentation provided with the library.
// See these sources for detailed information regarding the
// Active Template Library product.

#ifndef __ATLSIFACE_H__
#define __ATLSIFACE_H__

#pragma once
#include <atlcoll.h>
#include <httpext.h>
#include <atlserr.h>
#include <atlcom.h>
#include <string.h>
#include <atlpath.h>

#pragma pack(push,_ATL_PACKING)
namespace ATL{

// Forward declarations of custom data types used in 
// interfaces declared in this file.
struct AtlServerRequest;
class CIsapiWorker;
__interface IAtlMemMgr;
class CCookie;

// Forward declarations of all interfaces declared in this file.
__interface IWriteStream;
__interface IHttpFile;
__interface IHttpServerContext;
__interface IHttpRequestLookup;
__interface IRequestHandler;
__interface ITagReplacer;
__interface IIsapiExtension;
__interface IPageCacheControl;
__interface IRequestStats;
__interface IBrowserCaps;
__interface IBrowserCapsSvc;


// ATLS Interface declarations.

// IWriteStream
// Interface for writing to a stream.
__interface IWriteStream
{
	HRESULT WriteStream(LPCSTR szOut, int nLen, DWORD *pdwWritten);
	HRESULT FlushStream();
};

// IHttpFile
// This is an interface that provides for basic accessor
// functionality for files (see CHttpRequestFile).
__interface IHttpFile
{
	LPCSTR GetParamName();
	LPCSTR GetFileName();
	LPCSTR GetFullFileName();
	LPCSTR GetContentType();
	LPCSTR GetTempFileName();
	ULONGLONG GetFileSize();
	void Free();
};

// IHttpServerContext
// This interface encapsulates the capabilities of the web server and provides information about
// the current request being handled. See CServerContext for implementation.
__interface ATL_NO_VTABLE __declspec(uuid("813F3F00-3881-11d3-977B-00C04F8EE25E")) 
	IHttpServerContext : public IUnknown
{
	HRESULT  STDMETHODCALLTYPE QueryInterface(REFIID riid, void **ppv);
	ULONG STDMETHODCALLTYPE AddRef();
	ULONG STDMETHODCALLTYPE Release();

	LPCSTR GetRequestMethod();
	LPCSTR GetQueryString();
	LPCSTR GetPathInfo();
	LPCSTR GetPathTranslated();
	LPCSTR GetScriptPathTranslated();
	DWORD GetTotalBytes();
	DWORD GetAvailableBytes();
	BYTE *GetAvailableData();
	LPCSTR GetContentType();
	BOOL GetServerVariable(__in_z LPCSTR pszVariableName,
									__out_ecount_part_opt(*pdwSize, *pdwSize) LPSTR pvBuffer, __inout DWORD *pdwSize);
	BOOL GetImpersonationToken(HANDLE * pToken);
	BOOL WriteClient(void *pvBuffer, DWORD *pdwBytes);
	BOOL AsyncWriteClient(void *pvBuffer, DWORD *pdwBytes);
	BOOL ReadClient(void *pvBuffer, DWORD *pdwSize);
	BOOL AsyncReadClient(void *pvBuffer, DWORD *pdwSize);
	BOOL SendRedirectResponse(LPCSTR pszRedirectUrl);
	BOOL SendResponseHeader(LPCSTR pszHeader, LPCSTR pszStatusCode,
							BOOL fKeepConn);
	BOOL DoneWithSession(DWORD dwHttpStatusCode);
	BOOL RequestIOCompletion(PFN_HSE_IO_COMPLETION pfn, DWORD *pdwContext);
	BOOL TransmitFile(HANDLE hFile, PFN_HSE_IO_COMPLETION pfn, void *pContext, 
		LPCSTR szStatusCode, DWORD dwBytesToWrite, DWORD dwOffset,
		void *pvHead, DWORD dwHeadLen, void *pvTail,
		DWORD dwTailLen, DWORD dwFlags);
	BOOL AppendToLog(LPCSTR szMessage, DWORD* pdwLen);
	BOOL MapUrlToPathEx(LPCSTR szLogicalPath, DWORD dwLen, HSE_URL_MAPEX_INFO *pumInfo);
};

// IHttpRequestLookup
// This interface is designed to allow one map to chain to another map.
// The interface is implemented by the CHttpThunkMap and CHttpRequest classes.
// Pointers to this interface are passed around by CRequestHandlerT and CHtmlTagReplacer.
// dwType - the type of item being requested
__interface ATL_NO_VTABLE __declspec(uuid("A5990B44-FF74-4bfe-B66D-F9E7E9F42D42")) 
	IHttpRequestLookup : public IUnknown
{
	POSITION GetFirstQueryParam(LPCSTR *ppszName, LPCSTR *ppszValue);
	POSITION GetNextQueryParam(POSITION pos, LPCSTR *ppszName, LPCSTR *ppszValue);

	POSITION GetFirstFormVar(LPCSTR *ppszName, LPCSTR *ppszValue);
	POSITION GetNextFormVar(POSITION pos, LPCSTR *ppszName, LPCSTR *ppszValue);

	POSITION GetFirstFile(LPCSTR *ppszName, IHttpFile **ppFile);
	POSITION GetNextFile(POSITION pos, LPCSTR *ppszName, IHttpFile **ppFile);

	HRESULT GetServerContext(IHttpServerContext **ppOut);
};


// IRequestHandler
// This interface is impelemented by clients who want to be request handlers in an
// atl server application. Server default implementations are provided in ATL, including
// IRequestHandlerImpl (atlisapi.h) and CRequestHandlerT (atlstencil.h)
__interface ATL_NO_VTABLE __declspec(uuid("D57F8D0C-751A-4223-92BC-0B29F65D2453")) 
IRequestHandler : public IUnknown
{
	HTTP_CODE GetFlags(DWORD *pdwStatus);
	HTTP_CODE InitializeHandler(AtlServerRequest *pRequestInfo, IServiceProvider *pProvider);
	HTTP_CODE InitializeChild(AtlServerRequest *pRequestInfo, IServiceProvider *pProvider, IHttpRequestLookup *pLookup);
	HTTP_CODE HandleRequest(AtlServerRequest *pRequestInfo, IServiceProvider *pProvider);
	void UninitializeHandler();
};

// ITagReplacer
// This interface defines the methods necessary for server response file processing.
__interface ATL_NO_VTABLE __declspec(uuid("8FF5E90C-8CE0-43aa-96C4-3BF930837512")) 
	ITagReplacer : public IUnknown
{
	HTTP_CODE FindReplacementOffset(LPCSTR szMethodName, DWORD *pdwMethodOffset, 
						LPCSTR szObjectName, DWORD *pdwObjOffset, DWORD *pdwMap, void **ppvParam, IAtlMemMgr *pMemMgr);
	HTTP_CODE RenderReplacement(DWORD dwFnOffset, DWORD dwObjOffset, DWORD dwMap, void *pvParam);
	HRESULT GetContext(REFIID riid, void** ppv);
	IWriteStream *SetStream(IWriteStream *pStream);
};


struct CStencilState;

// IIsapiExtension
// Tnis is the interface to the ISAPI extension of a running ATL Server web
// application. Provides request handler clients with access to functions of the
// ISAPI server.
__interface __declspec(uuid("79DD4A27-D820-4fa6-954D-E1DFC2C05978"))
	IIsapiExtension : public IUnknown
{
	BOOL DispatchStencilCall(AtlServerRequest *pRequestInfo);
	void RequestComplete(AtlServerRequest *pRequestInfo, DWORD hStatus, DWORD dwSubStatus);
	BOOL OnThreadAttach();
	void OnThreadTerminate();
	BOOL QueueRequest(AtlServerRequest *pRequestInfo);
	CIsapiWorker *GetThreadWorker();
	BOOL SetThreadWorker(CIsapiWorker *pWorker);
	HTTP_CODE LoadRequestHandler(LPCSTR szDllPath, LPCSTR szHandlerName, IHttpServerContext *pServerContext,
		HINSTANCE *phInstance, IRequestHandler **ppHandler);
	HRESULT AddService(REFGUID guidService, REFIID riid, IUnknown *punk, HINSTANCE hInstance);
	HRESULT RemoveService(REFGUID guidService, REFIID riid);
	HTTP_CODE LoadDispatchFile(LPCSTR szFileName, AtlServerRequest *pRequestInfo);

	AtlServerRequest* CreateRequest();
	void FreeRequest(AtlServerRequest* pRequest);
	HTTP_CODE TransferRequest(
		AtlServerRequest *pRequest, 
		IServiceProvider *pServiceProvider,
		IWriteStream *pWriteStream,
		IHttpRequestLookup *pLookup,
		LPCSTR szNewUrl,
		WORD nCodePage,
		bool bContinueAfterProcess,
		CStencilState *pState);
};

// IPageCacheControl
// This interface controls the cacheability of the current page
__interface ATL_NO_VTABLE __declspec(uuid("9868BFC0-D44D-4154-931C-D186EC0C45D5")) 
	IPageCacheControl : public IUnknown
{
	HRESULT GetExpiration(FILETIME *pftExpiration);
	HRESULT SetExpiration(FILETIME ftExpiration);
	BOOL IsCached();
	BOOL Cache(BOOL bCache);
};

// IRequestStats
// Used to query request statistics from a running ATL server ISAPI application.
__interface ATL_NO_VTABLE __declspec(uuid("2B75C68D-0DDF-48d6-B58A-CC7C2387A6F2"))
	IRequestStats : public IUnknown
{
	long GetTotalRequests();
	long GetFailedRequests();
	long GetAvgResponseTime();
	long GetCurrWaiting();
	long GetMaxWaiting();
	long GetActiveThreads();
};

// IBrowserCaps
// Interface that provides information about a particular web brorwser.
// See atlutil.h and the ATL Browser Capabilities service for information
// about this interface's implementation
__interface __declspec(uuid("3339FCE2-99BC-4985-A702-4ABC8304A995"))
	IBrowserCaps : public IUnknown
{
	HRESULT GetPropertyString(BSTR bstrProperty, BSTR * pbstrOut);
	HRESULT GetBooleanPropertyValue(BSTR bstrProperty, BOOL* pbOut);
	HRESULT GetBrowserName(BSTR * pbstrName);
	HRESULT GetPlatform(BSTR * pbstrPlatform);
	HRESULT GetVersion(BSTR * pbstrVersion);
	HRESULT GetMajorVer(BSTR * pbstrMajorVer);
	HRESULT GetMinorVer(BSTR * pbstrMinorVer);
	HRESULT SupportsFrames(BOOL* pbFrames);
	HRESULT SupportsTables(BOOL* pbTables);
	HRESULT SupportsCookies(BOOL* pbCookies);
	HRESULT SupportsBackgroundSounds(BOOL* pbBackgroundSounds);
	HRESULT SupportsVBScript(BOOL* pbVBScript);
	HRESULT SupportsJavaScript(BOOL* pbJavaScript);
	HRESULT SupportsJavaApplets(BOOL* pbJavaApplets);
	HRESULT SupportsActiveXControls(BOOL* pbActiveXControls);
	HRESULT SupportsCDF(BOOL* pbCDF);
	HRESULT SupportsAuthenticodeUpdate(BOOL* pbAuthenticodeUpdate);
	HRESULT IsBeta(BOOL* pbIsBeta);
	HRESULT IsCrawler(BOOL* pbIsCrawler);
	HRESULT IsAOL(BOOL* pbIsAOL);
	HRESULT IsWin16(BOOL* pbIsWin16);
	HRESULT IsAK(BOOL* pbIsAK);
	HRESULT IsSK(BOOL* pbIsSK);
	HRESULT IsUpdate(BOOL* pbIsUpdate);
};

// IBrowserCapsSvc.
// Interface on the browser caps service. Used by clients to query a running
// instance of the browser capabilities service for information about a user's web
// browser. See atlutil.h for implementation of the browser capabilities services.
__interface __declspec(uuid("391E7418-863B-430e-81BB-1312ED2FF3E9"))
	IBrowserCapsSvc : public IUnknown
{
	HRESULT GetCaps(IHttpServerContext * pContext, IBrowserCaps ** ppOut);
	HRESULT GetCapsUserAgent(BSTR bstrAgent, IBrowserCaps ** ppOut);
};

class CBrowserCapsSvc : public IBrowserCapsSvc, 
						public CComObjectRootEx<CComSingleThreadModel>
{
public:
	virtual ~CBrowserCapsSvc()
	{
	}
	
	BEGIN_COM_MAP(CBrowserCapsSvc)
		COM_INTERFACE_ENTRY(IBrowserCapsSvc)
	END_COM_MAP()

	__success(SUCCEEDED(return)) __checkReturn HRESULT GetCaps(__in IHttpServerContext * pContext, __deref_out_opt IBrowserCaps ** ppOut)
	{
		if (!pContext)
			return E_POINTER;

		if (!ppOut)
			return E_POINTER;

		*ppOut = NULL;

		char szUserAgent[256];
		DWORD dwSize = sizeof(szUserAgent);
		if (!pContext->GetServerVariable("HTTP_USER_AGENT", szUserAgent, &dwSize))
			return E_FAIL;

		return GetCapsUserAgent(CComBSTR(szUserAgent), ppOut);
	}

	__success(SUCCEEDED(return)) __checkReturn HRESULT GetCapsUserAgent(__in BSTR bstrAgent, __deref_out IBrowserCaps ** ppOut)
	{
        if (::SysStringLen(bstrAgent) == 0 || ppOut == NULL)
        {
			return E_POINTER;
        }

		*ppOut = NULL;

		BrowserCaps* pCaps = NULL;

		_ATLTRY
		{
			CW2CT szUserAgent(bstrAgent);

			if (!m_mapAgent.Lookup(szUserAgent, pCaps))
			{
				pCaps = NULL;
				for (size_t i=0; i<m_caps.GetCount(); i++)
				{
					BrowserCaps& caps = m_caps[i];
					if (IsEqualAgentString(caps.m_strUserAgent, szUserAgent))
					{
						pCaps = &caps;
						break;
					}
				}
			}
		}
		_ATLCATCHALL()
		{
			return E_FAIL;
		}

#pragma warning(push)
#pragma warning(disable: 6014)
		if (pCaps != NULL)
		{
			CComObjectNoLock<CBrowserCaps> *pRet = NULL;

			ATLTRY(pRet = new CComObjectNoLock<CBrowserCaps>);

			if (!pRet)
				return E_OUTOFMEMORY;
			pRet->AddRef();

			HRESULT hr = pRet->Initialize(pCaps);
			if (FAILED(hr))
			{
				pRet->Release();
				return hr;
			}

			*ppOut = pRet;
			return S_OK;
		}
#pragma warning(pop)

		return E_FAIL;
	}

	__checkReturn HRESULT Initialize(__in HINSTANCE hInstance) throw()
	{
		// tries loading browscap.ini from the same directory as the module
		if (hInstance != NULL)
		{
			_ATLTRY
			{
				CPath strBrowscapPath;

				LPTSTR sz = strBrowscapPath.m_strPath.GetBuffer(MAX_PATH);
				UINT nChars = ::GetModuleFileName(hInstance, sz, MAX_PATH);
				strBrowscapPath.m_strPath.ReleaseBuffer(nChars);
				if (nChars != 0 &&
					nChars != MAX_PATH &&
					strBrowscapPath.RemoveFileSpec())
				{
					strBrowscapPath += _T("\\browscap.ini");
					if (SUCCEEDED(Load(strBrowscapPath)))
						return S_OK;
				}
			}
			_ATLCATCHALL()
			{
				return E_FAIL;
			}
		}

		// falls back to the system browscap.ini if previous Load failed
		return Load();
	}

	HRESULT Uninitialize()
	{
		Clear();
		return S_OK;
	}

private:
	static bool IsEqualAgentString(__in LPCTSTR szPattern, __in LPCTSTR szInput)
	{
		while (*szPattern && *szInput && (*szPattern == *szInput || *szPattern == '?'))
		{
			szPattern++;
			szInput++;
		}

		if (*szPattern == *szInput)
		{
			return true;
		}

		if (*szPattern == '*')
		{
			szPattern++;
			if (!*szPattern)
			{
				return true;
			}
			while(*szInput)
			{
				if (IsEqualAgentString(szPattern, szInput))
				{
					return true;
				}

				szInput++;
			}
		}

		return false;
	}

	__checkReturn HRESULT Load(__in_opt LPCTSTR szPath = NULL)
	{
		_ATLTRY
		{
			Clear();

			CString strBrowscapPath(szPath);

			// use default load path if a path isn't specified
			if (strBrowscapPath.IsEmpty())
			{
				LPTSTR sz = strBrowscapPath.GetBuffer(MAX_PATH);
				UINT nChars = ::GetSystemDirectory(sz, MAX_PATH);
				strBrowscapPath.ReleaseBuffer(nChars);
				if (nChars == 0 || nChars == MAX_PATH)
					return E_FAIL;

				strBrowscapPath += _T("\\inetsrv\\browscap.ini");
			}

			size_t nCurrent = 16384;
			CHeapPtr<TCHAR> data;

			if (!data.Allocate(nCurrent))
				return E_OUTOFMEMORY;

			// load the list of all the user agents
			bool bRetrieved = false;

			do
			{
				DWORD dwRetrieved = ::GetPrivateProfileSectionNames(data, (DWORD) nCurrent, strBrowscapPath);
				if (dwRetrieved == 0)
				{
					return AtlHresultFromWin32(ERROR_FILE_NOT_FOUND);			
				}
				else if (dwRetrieved < nCurrent-2)
				{
					bRetrieved = true;
				}
				else if(SIZE_MAX/2<nCurrent)
				{
					return E_OUTOFMEMORY;
				}
				else if (!data.Reallocate(nCurrent *= 2))
				{
					return E_OUTOFMEMORY;
				}
			} while (!bRetrieved);

			// figure out how many user agents there are
			// and set them in the structure
			LPTSTR sz = data;
			int nSections = 0;
			while (*sz)
			{
				nSections++;
				sz += (lstrlen(sz)+1);
			}

			if (!m_caps.SetCount(nSections))
				return E_OUTOFMEMORY;

			sz = data;
			nSections = 0;
			while (*sz)
			{
				BrowserCaps& caps = m_caps[nSections++];
				caps.m_strUserAgent = sz;
				m_mapAgent[caps.m_strUserAgent] = &caps;
				sz += (caps.m_strUserAgent.GetLength()+1);
			}

			// for each user agent, load the properties
			for (size_t i=0; i<m_caps.GetCount(); i++)
			{
				bRetrieved = false;
				BrowserCaps& caps = m_caps[i];
				caps.m_pParent = NULL;

				do
				{
					DWORD dwRetrieved = ::GetPrivateProfileSection(caps.m_strUserAgent, data, (DWORD) nCurrent, strBrowscapPath);
					if (dwRetrieved == 0)
					{
						return AtlHresultFromWin32(ERROR_FILE_NOT_FOUND);
					}
					else if (dwRetrieved < nCurrent-2)
					{
						bRetrieved = true;
					}	
					else if(SIZE_MAX/2<nCurrent)
					{
						return E_OUTOFMEMORY;
					}
					else if (!data.Reallocate(nCurrent *= 2))
					{
						return E_OUTOFMEMORY;
					}
				} while (!bRetrieved);

				sz = data;
				while (*sz)
				{
					CString str = sz;
					int nChar = str.Find('=');
					if (nChar != -1)
					{
						CString strPropName = str.Left(nChar);
						CString strPropVal = str.Mid(nChar+1);
						strPropName.Trim();
						strPropVal.Trim();
						caps.m_props.SetAt(strPropName, strPropVal);

						// if it's the parent property, set up the parent pointer
						if (strPropName.CompareNoCase(_T("parent")) == 0)
						{
							BrowserCaps* pParent = NULL;
							if (m_mapAgent.Lookup(strPropVal, pParent))
								caps.m_pParent = pParent;
						}
					}
					sz += (str.GetLength()+1);
				}
			}
		}
		_ATLCATCHALL()
		{
			return E_FAIL;
		}

		return S_OK;
	}

	void Clear()
	{
		m_caps.RemoveAll();
		m_mapAgent.RemoveAll();
	}

	friend class CBrowserCaps;

	struct BrowserCaps
	{
		CString m_strUserAgent; // user agent string to match against (with wildcards)
		BrowserCaps* m_pParent;
		CAtlMap<CString, CString, CStringElementTraitsI<CString>, CStringElementTraits<CString> > m_props;
	};

	// map from UserAgent string to caps
	// used for non-wildcard lookup and parent lookup
	CAtlMap<CString, BrowserCaps*, CStringElementTraits<CString> > m_mapAgent;

	// all of the caps
	CAtlArray<BrowserCaps> m_caps;

	class CBrowserCaps : public IBrowserCaps, public CComObjectRootEx<CComSingleThreadModel>
	{
	public:

		BEGIN_COM_MAP(CBrowserCaps)
			COM_INTERFACE_ENTRY(IBrowserCaps)
		END_COM_MAP()

		CBrowserCaps()
		{
		}

		HRESULT Initialize(__in CBrowserCapsSvc::BrowserCaps * pCaps)
		{
			m_pCaps = pCaps;
			return S_OK;
		}

		__checkReturn HRESULT GetPropertyString(__in BSTR bstrProperty, __out BSTR * pbstrOut)
		{
			_ATLTRY
			{
				ATLASSUME(m_pCaps);
				if (!m_pCaps)
					return E_UNEXPECTED;

				if (!pbstrOut)
					return E_POINTER;

				*pbstrOut = NULL;

				CString strName(bstrProperty);
				CString strVal;

				CBrowserCapsSvc::BrowserCaps * pCaps = m_pCaps;
				while (pCaps)
				{
					if (pCaps->m_props.Lookup(strName, strVal))
					{
						CComBSTR bstrVal(strVal);
						*pbstrOut = bstrVal.Detach();
						return S_OK;
					}

					pCaps = pCaps->m_pParent;
				}

				return S_FALSE;
			}
			_ATLCATCHALL()
			{
				return E_FAIL;
			}
		}

		__checkReturn HRESULT GetBooleanPropertyValue(__in BSTR bstrProperty, __out BOOL* pbOut)
		{
			if (!pbOut)
				return E_POINTER;

			CComBSTR bstrOut;
			HRESULT hr = GetPropertyString(bstrProperty, &bstrOut);
			if (FAILED(hr) || S_FALSE == hr)
				return hr;

			if (_wcsicmp(bstrOut, L"true") == 0)
				*pbOut = TRUE;
			else
				*pbOut = FALSE;

			return S_OK;
		}

		__checkReturn HRESULT GetBrowserName(__out BSTR * pbstrName)
		{
			return GetPropertyString(CComBSTR(L"browser"), pbstrName);
		}

		__checkReturn HRESULT GetPlatform(__out BSTR * pbstrPlatform)
		{
			return GetPropertyString(CComBSTR(L"platform"), pbstrPlatform);
		}

		__checkReturn HRESULT GetVersion(__out BSTR * pbstrVersion)
		{
			return GetPropertyString(CComBSTR(L"version"), pbstrVersion);
		}

		__checkReturn HRESULT GetMajorVer(__out BSTR * pbstrMajorVer)
		{
			return GetPropertyString(CComBSTR(L"majorver"), pbstrMajorVer);
		}

		__checkReturn HRESULT GetMinorVer(__out BSTR * pbstrMinorVer)
		{
			return GetPropertyString(CComBSTR(L"minorver"), pbstrMinorVer);
		}

		__checkReturn HRESULT SupportsFrames(__out BOOL* pbFrames)
		{
			return GetBooleanPropertyValue(CComBSTR(L"frames"), pbFrames);
		}

		__checkReturn HRESULT SupportsTables(__out BOOL* pbTables)
		{
			return GetBooleanPropertyValue(CComBSTR(L"tables"), pbTables);
		}
		__checkReturn HRESULT SupportsCookies(__out BOOL* pbCookies)
		{
			return GetBooleanPropertyValue(CComBSTR(L"cookies"), pbCookies);
		}
		__checkReturn HRESULT SupportsBackgroundSounds(__out BOOL* pbBackgroundSounds)
		{
			return GetBooleanPropertyValue(CComBSTR(L"backgroundsounds"), pbBackgroundSounds);
		}
		__checkReturn HRESULT SupportsVBScript(__out BOOL* pbVBScript)
		{
			return GetBooleanPropertyValue(CComBSTR(L"vbscript"), pbVBScript);
		}
		__checkReturn HRESULT SupportsJavaScript(__out BOOL* pbJavaScript)
		{
			return GetBooleanPropertyValue(CComBSTR(L"javascript"), pbJavaScript);
		}
		__checkReturn HRESULT SupportsJavaApplets(__out BOOL* pbJavaApplets)
		{
			return GetBooleanPropertyValue(CComBSTR(L"javaapplets"), pbJavaApplets);
		}
		__checkReturn HRESULT SupportsActiveXControls(__out BOOL* pbActiveXControls)
		{
			return GetBooleanPropertyValue(CComBSTR(L"ActiveXControls"), pbActiveXControls);
		}
		__checkReturn HRESULT SupportsCDF(__out BOOL* pbCDF)
		{
			return GetBooleanPropertyValue(CComBSTR(L"CDF"), pbCDF);
		}
		__checkReturn HRESULT SupportsAuthenticodeUpdate(__out BOOL* pbAuthenticodeUpdate)
		{
			return GetBooleanPropertyValue(CComBSTR(L"AuthenticodeUpdate"), pbAuthenticodeUpdate);
		}
		__checkReturn HRESULT IsBeta(__out BOOL* pbIsBeta)
		{
			return GetBooleanPropertyValue(CComBSTR(L"beta"), pbIsBeta);
		}
		__checkReturn HRESULT IsCrawler(__out BOOL* pbIsCrawler)
		{
			return GetBooleanPropertyValue(CComBSTR(L"Crawler"), pbIsCrawler);
		}
		__checkReturn HRESULT IsAOL(__out BOOL* pbIsAOL)
		{
			return GetBooleanPropertyValue(CComBSTR(L"AOL"), pbIsAOL);
		}
		__checkReturn HRESULT IsWin16(__out BOOL* pbIsWin16)
		{
			return GetBooleanPropertyValue(CComBSTR(L"Win16"), pbIsWin16);
		}
		__checkReturn HRESULT IsAK(__out BOOL* pbIsAK)
		{
			return GetBooleanPropertyValue(CComBSTR(L"AK"), pbIsAK);
		}
		__checkReturn HRESULT IsSK(__out BOOL* pbIsSK)
		{
			return GetBooleanPropertyValue(CComBSTR(L"SK"), pbIsSK);
		}
		__checkReturn HRESULT IsUpdate(__out BOOL* pbIsUpdate) 
		{
			return GetBooleanPropertyValue(CComBSTR(L"Update"), pbIsUpdate);
		}

	private:
		CBrowserCapsSvc::BrowserCaps * m_pCaps;
	};
};

typedef DWORD_PTR HSESSIONENUM;

// ISession
// Interface on a single client session. Used to access variables in the client 
// session in the session state services. See atlsession.h for implementation of
// this interface.
__interface __declspec(uuid("DEB69BE3-7AC9-4a13-9519-266C1EA3AB39")) 
	ISession : public IUnknown
{
	STDMETHOD(SetVariable)(LPCSTR szName, VARIANT NewVal);
	STDMETHOD(GetVariable)(LPCSTR szName, VARIANT *pVal);
	STDMETHOD(GetCount)(long *pnCount);
	STDMETHOD(RemoveVariable)(LPCSTR szName);
	STDMETHOD(RemoveAllVariables)();
	STDMETHOD(BeginVariableEnum)(POSITION *pPOS, HSESSIONENUM *phEnumHandle);
	STDMETHOD(GetNextVariable)(POSITION *pPOS, VARIANT *pVal, HSESSIONENUM hEnum, LPSTR szName, DWORD dwLen);
	STDMETHOD(CloseEnum)(HSESSIONENUM hEnumHandle);
	STDMETHOD(IsExpired)();
	STDMETHOD(SetTimeout)(unsigned __int64 dwNewTimeout);
}; //ISession


// ISessionStateService
// Interface on the session state service for an ISAPI application. Request
// handler objects will use this interface to access user sessions. See
// atlsession.h for implementation of this interface.
__interface __declspec(uuid("C5740C4F-0C6D-4b43-92C4-2AF778F35DDE"))
	ISessionStateService : public IUnknown
{
	STDMETHOD(CreateNewSession)(LPSTR szNewID, DWORD *pdwSize, ISession** ppSession);
	STDMETHOD(CreateNewSessionByName)(LPSTR szNewID, ISession** ppSession);
	STDMETHOD(GetSession)(LPCSTR szID, ISession **ppSession);
	STDMETHOD(CloseSession)(LPCSTR szID);
};

// ISessionStateControl
// Interface used by session state service to get information about the service.
// Currently you can get the count of active sessions and the current default
// timeout for a session.
__interface __declspec(uuid("6C7F5F56-6CBD-49ee-9797-4C837D4C527A"))
	ISessionStateControl : public IUnknown
{
	STDMETHOD(SetSessionTimeout)(unsigned __int64 nTimeout);
	STDMETHOD(GetSessionTimeout)(unsigned __int64 *pnTimeout);
	STDMETHOD(GetSessionCount)(DWORD *pnSessionCount);
}; 

}; // namespace ATL
#pragma pack(pop)

#endif // __ATLSIFACE_H__
