📄 atlrt.cpp
字号:
// atlrt.cpp : Defines the entry point for the DLL application.
//
// Copyright (c) Microsoft Corporation. All rights reserved.
//
// This source code is only intended as a supplement to the
// Microsoft Classes Reference and related electronic
// documentation provided with the library.
// See these sources for detailed information regarding the
// Microsoft C++ Libraries products.
#include "stdafx.h"
// For custom assert and trace handling with WebDbg.exe
#ifdef _DEBUG
CDebugReportHook g_ReportHook;
#endif
#include "atlrt.h"
[ module(name="atlrt", type="dll") ];
[ emitidl(restricted) ];
#include "atlrtextension.h"
HTTP_CODE CATLRTHandler::ValidateAndExchange()
{
Trace::TraceMsg("CATLRTHandler ValidateAndExchange");
// Get the IMemoryCache service from the ISAPI extension
if (FAILED(m_spServiceProvider->QueryService(__uuidof(IMemoryCache),
__uuidof(IMemoryCache), (void **)&m_spBinaryCache)))
return HTTP_FAIL;
// Get the IDataSourceCache service from the ISAPI extension
if (FAILED(m_spServiceProvider->QueryService(__uuidof(IDataSourceCache),
__uuidof(IDataSourceCache), (void **)&m_spDataSrcCache)))
return HTTP_FAIL;
// get or create our variable map
HCACHEITEM cacheHandle;
HRESULT hr = m_spBinaryCache->LookupEntry(VARIABLE_MAP, &cacheHandle);
if (FAILED(hr))
{
// we need to create a variable map
m_variableMap = new StringMap();
hr = m_spBinaryCache->Add(VARIABLE_MAP,
(void*)m_variableMap,
sizeof(StringMap),
NULL,
NULL,
NULL,
NULL);
if (FAILED(hr))
{
Trace::TraceMsg("CATLRTHandler ValidateAndExchange can't create variable map!");
return hr;
}
}
else
{
// get the variable map pointer from the cache
DWORD dwSize = 0;
hr = m_spBinaryCache->GetData(cacheHandle, (void**)&m_variableMap, &dwSize);
if (FAILED(hr) || !m_variableMap)
{
Trace::TraceMsg("CATLRTHandler ValidateAndExchange can't get variable map!");
return hr;
}
}
// get or create our connection time
hr = m_spBinaryCache->LookupEntry(CONNECTION_MAP, &cacheHandle);
if (FAILED(hr))
{
// we need to create a variable map
m_connectionMap = new StringMap();
hr = m_spBinaryCache->Add(CONNECTION_MAP,
(void*)m_connectionMap,
sizeof(StringMap),
NULL,
NULL,
NULL,
NULL);
if (FAILED(hr))
{
Trace::TraceMsg("CATLRTHandler ValidateAndExchange can't create connection map!");
return hr;
}
}
else
{
// get the variable map pointer from the cache
DWORD dwSize = 0;
hr = m_spBinaryCache->GetData(cacheHandle, (void**)&m_connectionMap, &dwSize);
if (FAILED(hr) || !m_connectionMap)
{
Trace::TraceMsg("CATLRTHandler ValidateAndExchange can't get connection map!");
return hr;
}
}
CloseHandle(cacheHandle);
return HTTP_SUCCESS;
}
HTTP_CODE CATLRTHandler::Uninitialize(HTTP_CODE hcError) throw( )
{
Trace::TraceMsg("CATLRTHandler Uninitialize");
return HTTP_SUCCESS;
}
/////////////////////////////////////////////////////////////////////
// Variable Map Operations
/////////////////////////////////////////////////////////////////////
HTTP_CODE CATLRTHandler::OnGetValue(TCHAR *szVariableName)
{
ASSERT(szVariableName);
if (szVariableName == NULL)
return HTTP_SUCCESS;
LPCSTR szValue = NULL;
// try to find the variable value in our variable map or in the request parameters
szValue = _GetValue(CStringA(szVariableName));
// if we got a value from either place, output it
if (szValue != NULL)
{
m_HttpResponse << szValue;
}
return HTTP_SUCCESS;
}
HTTP_CODE CATLRTHandler::OnCopyValue(TCHAR *szArgs)
{
ASSERT(szArgs);
if (!szArgs)
return HTTP_SUCCESS;
ArgParser parser;
if (!parser.Parse(szArgs))
return HTTP_SUCCESS;
// need 'source' and 'dest' attributes
CStringA source;
CStringA dest;
if (parser.GetAttribute("source", source) != 1)
return HTTP_SUCCESS;
if (parser.GetAttribute("dest", dest) != 1)
return HTTP_SUCCESS;
// get the value specified by source
LPCSTR szSourceValue = _GetValue(source);
if (!szSourceValue)
return HTTP_SUCCESS;
// insert this value into the destination name
m_variableMap->SetAt(dest, szSourceValue);
return HTTP_SUCCESS;
}
HTTP_CODE CATLRTHandler::OnContainsValue(TCHAR *szName)
{
if (!szName)
return HTTP_S_FALSE;
if (!_GetValue(CStringA(szName)))
return HTTP_S_FALSE;
else
return HTTP_SUCCESS;
}
HTTP_CODE CATLRTHandler::OnCompareValue(TCHAR *szArgs)
{
if (!szArgs)
return HTTP_S_FALSE;
ArgParser parser;
if (!parser.Parse(szArgs))
return HTTP_S_FALSE;
// get the 'name' and 'value' attributes, both are required
CStringA name;
CStringA value;
if (parser.GetAttribute("name", name) != 1)
return HTTP_S_FALSE;
if (parser.GetAttribute("value", value) != 1)
return HTTP_S_FALSE;
// get the value specified by 'name1'
LPCSTR szValue1 = _GetValue(name);
if (!szValue1)
return HTTP_S_FALSE;
// compare the values
if (strcmp(szValue1, value) != 0)
{
return HTTP_S_FALSE;
}
else
{
return HTTP_SUCCESS;
}
}
HTTP_CODE CATLRTHandler::OnMaintainValue(TCHAR *szArgs)
{
if (!szArgs)
return HTTP_SUCCESS;
ArgParser parser;
CStringA var_name;
CStringA state_name;
// see if we have an arg list (ie. a=b;c=d)
if (!parser.Parse(szArgs)) // if we don't, use the whole CStringA as the name
{
var_name = szArgs;
state_name = szArgs;
}
else // if we do, parse out the values
{
if (parser.GetAttribute("name", var_name) != 1)
return HTTP_SUCCESS;
if (parser.GetAttribute("save_as", state_name) != 1)
return HTTP_SUCCESS;
}
// get the value specified by var_name
LPCSTR szValue = _GetValue(var_name);
if (!szValue)
return HTTP_SUCCESS;
// save this value as a hidden input field
CStringA hiddenField;
hiddenField.Format("<input type=\"hidden\" value=\"%s\" name=\"%s\">", szValue, state_name);
m_HttpResponse << hiddenField;
return HTTP_SUCCESS;
}
/////////////////////////////////////////////////////////////////////
// Database Operations
/////////////////////////////////////////////////////////////////////
HTTP_CODE CATLRTHandler::OnSetConnection(TCHAR *szArgs)
{
if (!szArgs)
{
m_HttpResponse << "ERROR: missing argument CStringA";
m_HttpResponse << USEAGE_SETCONNECTION;
return HTTP_SUCCESS;
}
ArgParser parser;
// look for server,
CStringA name;
CStringA conn;
if (!parser.Parse(szArgs))
{
name = DEFAULT_CONNECTION;
// we have to treat this string carefully, if there are enclosing quotes, then
// these quotes have to be removed
if (*szArgs == '\"')
{
int length = strlen(szArgs);
// we don't want the first and last characters in szArgs, which are "'s
for (int i = 1; i < length - 1; i++)
{
conn += szArgs[i];
}
}
else
{
conn = szArgs;
}
}
else
{
if (parser.GetAttribute("name", name) != 1)
{
m_HttpResponse << "ERROR: missing name attribute";
m_HttpResponse << USEAGE_SETCONNECTION;
return HTTP_SUCCESS;
}
if (parser.GetAttribute("conn", conn) != 1)
{
m_HttpResponse << "ERROR: missing conn attribute";
m_HttpResponse << USEAGE_SETCONNECTION;
return HTTP_SUCCESS;
}
}
// put the connection CStringA into our map
m_connectionMap->SetAt(name, conn);
return HTTP_SUCCESS;
}
HTTP_CODE CATLRTHandler::OnExecute(TCHAR *szArgs)
{
if (!szArgs)
return HTTP_S_FALSE;
// look for:
// cmd (required)
// conn (optional, default to 'default_connection'
// results (optional, default to 'default_result'
// input_params (optional)
// output_params (optional)
ArgParser parser;
if (!parser.Parse(szArgs))
return HTTP_S_FALSE;
CStringA cmd;
if (parser.GetAttribute("cmd", cmd) != 1)
return HTTP_S_FALSE;
CStringA conn;
if (parser.GetAttribute("conn", conn) != 1)
conn = DEFAULT_CONNECTION;
// we could have multiple result names or none at all
StringList resultNames;
parser.GetAttribute("results", resultNames);
// set a default value if we don't have any result names
if (resultNames.GetCount() == 0)
resultNames.AddTail(DEFAULT_RESULTS);
// we could have multiple input parameter names or none at all
Params inputParamNames;
StringList inputParams;
parser.GetAttribute("params", inputParamNames);
int inputParamCount = inputParamNames.GetCount();
if (inputParamCount > 0)
{
// resolve our parameter values
if (_ResolveParameters(inputParamNames, inputParams) <= 0)
{
// just get out of here, _ResolveParameters has already outputted
// an error message
// return HTTP_S_FALSE to stop processing so we don't crash
// on calls that depend on this function succeeding
return HTTP_S_FALSE;
}
}
// we could have multiple output parameter names or none at all
StringList outputParams;
parser.GetAttribute("output_params", outputParams);
// create a builder to add to our cmd results map
ResultSetBuilder builder(&resultNames, &outputParams, m_variableMap);
// create a data connection factory that will hide all the
// data cache pooling and creation details
DataConnectionFactory dataConnectionFactory(m_spDataSrcCache);
// create a cmd info factory that will hide all the details
// involving getting information about a stored procedure
CmdInfoFactory cmdInfoFactory(m_spBinaryCache);
// execute our command
DBCommand command(&builder, &dataConnectionFactory, &cmdInfoFactory);
HRESULT hr;
if (FAILED((hr = command.Execute( cmd,
(*m_connectionMap)[conn],
inputParams))))
{
// we could not execute the stored proc, tell the user and
// get out of here
m_HttpResponse << "execute command: " << cmd << " failed" << " " << hr;
// return HTTP_S_FALSE to stop processing so we don't crash
// on calls that depend on this function succeeding
return HTTP_S_FALSE;
}
// if we succeeded, get the results
builder.GetResults(m_resultsMap);
return HTTP_SUCCESS;
}
HTTP_CODE CATLRTHandler::OnMoveNextRow(TCHAR *szArgs)
{
CStringA resultsName;
if (!szArgs)
{
// if we get a NULL argument, use 'DEFAULT_RESULTS' as the results name
resultsName = DEFAULT_RESULTS;
}
else
{
// otherwise, take the whole argument string as the result name
resultsName = szArgs;
}
// if we get here, then we have a valid results name, either the default or
// the one the user specified
// see if we have a CmdResult using this results name as the key
if (!_CheckForResults(resultsName))
{
// getting here means we have no results for the specified name, _CheckForResults
// has already sent an error message so we can just return
return HTTP_S_FALSE;
}
// otherwise, move the result set along
if (m_resultsMap[resultsName].MoveNextRow())
{
return HTTP_SUCCESS;
}
else
{
// MoveNextRow will be used in a loop, so returning HTTP_S_FALSE will stop
// the loop
return HTTP_S_FALSE;
}
}
HTTP_CODE CATLRTHandler::OnMoveNextColumn(TCHAR *szArgs)
{
CStringA resultsName;
if (!szArgs)
{
// if we get a NULL argument, use 'DEFAULT_RESULTS' as the results name
resultsName = DEFAULT_RESULTS;
}
else
{
// otherwise, take the whole argument string as the result name
resultsName = szArgs;
}
// if we get here, then we have a valid results name, either the default or
// the one the user specified
// see if we have a CmdResult using this results name as the key
if (!_CheckForResults(resultsName))
{
// getting here means we have no results for the specified name, _CheckForResults
// has already sent an error message so we can just return
return HTTP_S_FALSE;
}
// otherwise, move the result set along
if (m_resultsMap[resultsName].MoveNextColumn())
{
return HTTP_SUCCESS;
}
else
{
// MoveNextColumn will be used in a loop, so returning HTTP_S_FALSE will stop
// the loop
return HTTP_S_FALSE;
}
}
HTTP_CODE CATLRTHandler::OnGetColumnValue(TCHAR *szArgs)
{
// szArgs has 4 possiblities, look for each one in the following code:
// 1. szArgs == NULL - this means we'll use the default result name and the current column
// value stored for that result
// 2. szArgs == "name=value;" - this means we'll use the specified result name and the current
// value stored for that result
// 3. szArgs == "name=value;column=col" - this means we'll use the specified result name and the
// specified column value.
// 4. szArgs == "column index" - this means we'll use the default result name and the specified column
// value
CStringA resultsName;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -