📄 extns.cpp
字号:
// Connection header determined by fKeepConn of passed in struct
CHttpResponse resp(this, STATUS_OK,
pHeaderEx->fKeepConn ? CONN_KEEP : CONN_CLOSE);
m_fKeepAlive = pHeaderEx->fKeepConn;
// no body, default or otherwise (leave that to the ISAPI), but add default headers
resp.SendResponse(pHeaderEx->pszHeader, pHeaderEx->pszStatus);
return TRUE;
}
case HSE_APPEND_LOG_PARAMETER:
{
return MyStrCatA(&m_pszLogParam,(PSTR) pvBuf,",");
}
// HSE_REQ_GET_LOCAL_SOCKADDR and HSE_REQ_GET_REMOTE_SOCKADDR are WinCE
// extensions to ISAPI's. Makes it possible for apps to retrieve
// the SOCKADDR of either local or remote client.
case HSE_REQ_GET_LOCAL_SOCKADDR:
{
return (0 == getsockname(m_socket,(PSOCKADDR)pvBuf,(int*)pdwSize));
}
case HSE_REQ_GET_REMOTE_SOCKADDR:
{
return (0 == getpeername(m_socket,(PSOCKADDR)pvBuf,(int*)pdwSize));
}
}
}
BOOL CHttpRequest::MapURLToPath(PSTR pszBuffer, PDWORD pdwSize, LPHSE_URL_MAPEX_INFO pUrlMapEx)
{
PWSTR wszPath;
PSTR pszURL;
DWORD dwBufNeeded = 0;
BOOL ret;
PVROOTINFO pVRoot;
wszPath = m_pWebsite->m_pVroots->URLAtoPathW(pszBuffer,&pVRoot);
if(!wszPath) {
// Assume failure on matching to virtual root, and not on mem alloc
SetLastError(ERROR_INVALID_PARAMETER);
return FALSE;
}
dwBufNeeded = (DWORD) WideCharToMultiByte(CP_ACP,0, wszPath, -1, pszBuffer, 0 ,0,0);
// For MAP_EX case, we set these vars from the passed structure, else we use the raw ptrs.
if (pUrlMapEx) {
pszURL = pUrlMapEx->lpszPath;
*pdwSize = MAX_PATH;
}
else {
pszURL = pszBuffer;
}
// To keep compat with IIS, we translate "/" to "\". We do the conversion
// only if we're using filters or if there's enough space in the buffer.
if (g_pVars->m_fFilters || *pdwSize >= dwBufNeeded) {
for (int i = 0; i < (int) wcslen(wszPath); i++) {
if ( wszPath[i] == L'/')
wszPath[i] = L'\\';
}
}
if (FALSE == g_pVars->m_fFilters) {
// We check to make sure buffer is the right size because WideToMultyByte
// will overwrite pieces of pszURL even on failure, leaving pszURL's
// content invalid
if (*pdwSize < dwBufNeeded) {
SetLastError(ERROR_INSUFFICIENT_BUFFER);
ret = FALSE;
}
else {
MyW2A(wszPath, pszURL, *pdwSize);
ret = TRUE;
}
*pdwSize = dwBufNeeded;
}
else {
// for EX case, put original URL as optional 5th parameter.
ret = FilterMapURL(pszURL, wszPath, pdwSize,dwBufNeeded, pUrlMapEx ? pszBuffer : NULL);
}
if (ret && pUrlMapEx) {
pUrlMapEx->cchMatchingPath = *pdwSize - 1; // don't count \0
pUrlMapEx->cchMatchingURL = strlen(pszBuffer);
pUrlMapEx->dwFlags = pVRoot->dwPermissions;
}
MyFree(wszPath);
return ret;
}
void CISAPI::Unload(PWSTR wszDLLName) {
if(m_pfnTerminate) {
__try {
if(SCRIPT_TYPE_FILTER == m_scriptType)
((PFN_TERMINATEFILTER)m_pfnTerminate)(HSE_TERM_MUST_UNLOAD);
else if (SCRIPT_TYPE_EXTENSION == m_scriptType)
((PFN_TERMINATEEXTENSION)m_pfnTerminate)(HSE_TERM_MUST_UNLOAD);
else if (SCRIPT_TYPE_ASP == m_scriptType)
((PFN_TERMINATEASP)m_pfnTerminate)();
}
__except(ReportFault(GetExceptionInformation(),0), EXCEPTION_EXECUTE_HANDLER) {
DWORD dwExceptionCode = SCRIPT_TYPE_FILTER == m_scriptType ?
IDS_HTTPD_FILT_EXCEPTION : IDS_HTTPD_EXT_EXCEPTION;
PWSTR wszFunction = SCRIPT_TYPE_FILTER == m_scriptType ?
L"TerminateFilter" : L"TerminateExtension";
DEBUGMSG(ZONE_ERROR, (L"HTTPD: TerminateExtension faulted\r\n"));
g_pVars->m_pLog->WriteEvent(dwExceptionCode,wszDLLName ? wszDLLName : m_wszDLLName,
GetExceptionCode(),wszFunction,GetLastError());
}
}
MyFreeLib(m_hinst);
m_hinst = NULL;
m_pfnTerminate = NULL;
}
// To see if two file names are equal,
// do a normal string compare with the difference that "/" and "\" are treated
// as equiavalents. (They may not be same in two passed variables due to the
// way web server does VRoot name mapping).
// Format like wcsicmp, returns 0 if strings are equal.
int PathNameCompare(WCHAR *src, WCHAR *dst) {
WCHAR f,l;
BOOL fSlashMatch;
do {
fSlashMatch = (*dst == L'/' || *dst == L'\\') && (*src == L'/' || *src == L'\\');
f = towlower(*dst++);
l = towlower(*src++);
} while (f && ((f == l) || fSlashMatch));
if (fSlashMatch)
return 0;
return (int)(f - l);
}
int PathNameCompareN(WCHAR *src, WCHAR *dst, int len) {
WCHAR f,l;
BOOL fSlashMatch;
do {
fSlashMatch = (*dst == L'/' || *dst == L'\\') && (*src == L'/' || *src == L'\\');
f = towlower(*dst++);
l = towlower(*src++);
} while (f && ((f == l) || fSlashMatch) && --len);
if (fSlashMatch)
return 0;
return (int)(f - l);
}
BOOL IsScriptInNoUnloadList(WCHAR *szDLLName) {
for (DWORD i = 0; i < g_pVars->m_scriptNoUnload.dwEntries; i++) {
if (0 == PathNameCompare(g_pVars->m_scriptNoUnload.ppszNoUnloadEntry[i],szDLLName))
return TRUE;
}
return FALSE;
}
BOOL CISAPI::LoadExports(HINSTANCE hInst, BOOL fVerifyOnly) {
BOOL fRet = FALSE;
if (SCRIPT_TYPE_ASP == m_scriptType) {
m_pfnHttpProc = GetProcAddress(hInst, CE_STRING("ExecuteASP"));
m_pfnTerminate = GetProcAddress(hInst, CE_STRING("TerminateASP"));
fRet = (m_pfnHttpProc && m_pfnTerminate);
goto done;
}
if (SCRIPT_TYPE_EXTENSION == m_scriptType) {
m_pfnGetVersion = GetProcAddress(hInst, CE_STRING("GetExtensionVersion"));
m_pfnHttpProc = GetProcAddress(hInst, CE_STRING("HttpExtensionProc"));
m_pfnTerminate = GetProcAddress(hInst, CE_STRING("TerminateExtension"));
}
else if (SCRIPT_TYPE_FILTER == m_scriptType) {
m_pfnGetVersion = GetProcAddress(hInst, CE_STRING("GetFilterVersion"));
m_pfnHttpProc = GetProcAddress(hInst, CE_STRING("HttpFilterProc"));
m_pfnTerminate = GetProcAddress(hInst, CE_STRING("TerminateFilter"));
}
else {
DEBUGCHK(0); // unknown script type
}
fRet = (m_pfnHttpProc && m_pfnGetVersion);
done:
if (fVerifyOnly) {
// NULL out proc ptrs since we'll be unloading DLL data file.
m_pfnGetVersion = m_pfnHttpProc = m_pfnTerminate = NULL;
}
return fRet;
}
BOOL CISAPI::Load(PWSTR wszPath) {
// First we load the ISAPI as a LOAD_LIBRARY_AS_DATAFILE and verify
// that it has the proper exports for given ISAPI. We do this
// because it guarantees that DllMain() won't be called until we're
// sure we really are dealing with an ISAPI extension.
HINSTANCE hLibData = LoadLibraryEx(wszPath,NULL,DONT_RESOLVE_DLL_REFERENCES);
if (!hLibData) {
DEBUGMSG(ZONE_ERROR,(L"HTTPD: LoadLibraryEx(%s) fails. GLE=0x%08x\r\n",wszPath,GetLastError()));
return FALSE;
}
if (! LoadExports(hLibData,TRUE)) {
FreeLibrary(hLibData);
return FALSE;
}
FreeLibrary(hLibData);
// Now load the DLL "for real"
m_hinst = LoadLibrary(wszPath);
if(!m_hinst)
return FALSE;
if (SCRIPT_TYPE_EXTENSION == m_scriptType || SCRIPT_TYPE_ASP == m_scriptType)
m_fCanTimeout = ! (IsScriptInNoUnloadList(wszPath));
if (! LoadExports(m_hinst,FALSE))
goto done;
__try {
// call GetVersion immediately after load on extensions and Filters, but not ASP
// if it's a filter we need to do some flags work first
if(SCRIPT_TYPE_FILTER == m_scriptType) {
HTTP_FILTER_VERSION vFilt;
// IIS ignores ISAPI version info, so do we.
PREFAST_ASSERT(m_pfnGetVersion != NULL); // LoadExports verifies that m_pfnGetVersion != NULL.
((PFN_GETFILTERVERSION)m_pfnGetVersion)(&vFilt);
dwFilterFlags = vFilt.dwFlags;
// client didn't set the prio flags, assign them to default
// If they set more than one prio we use the highest + ignore others
if (0 == (dwFilterFlags & SF_NOTIFY_ORDER_MASK)) {
dwFilterFlags |= SF_NOTIFY_ORDER_DEFAULT;
}
// If the Filter set neither SF_NOTIFY_SECURE_PORT nor SF_NOTIFY_NONSECURE_PORT
// then we notify them for both.
if (0 == (dwFilterFlags & (SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT))) {
dwFilterFlags |= SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT;
}
}
else if (SCRIPT_TYPE_EXTENSION == m_scriptType) {
HSE_VERSION_INFO vExt;
// IIS ignores ISAPI version info, so do we.
((PFN_GETEXTENSIONVERSION)m_pfnGetVersion)(&vExt);
}
return TRUE;
}
__except(ReportFault(GetExceptionInformation(),0), EXCEPTION_EXECUTE_HANDLER) {
DWORD dwExceptionCode = SCRIPT_TYPE_FILTER == m_scriptType ?
IDS_HTTPD_FILT_EXCEPTION : IDS_HTTPD_EXT_EXCEPTION;
PWSTR wszFunction = SCRIPT_TYPE_FILTER == m_scriptType ?
L"GetFilterVersion" : L"GetExtensionVersion";
DEBUGMSG(ZONE_ERROR, (L"HTTPD: GetExtensionVersion faulted\r\n"));
g_pVars->m_pLog->WriteEvent(dwExceptionCode,wszPath,GetExceptionCode(),wszFunction,GetLastError());
}
// fall through to error
done:
m_pfnGetVersion = 0;
m_pfnHttpProc = 0;
m_pfnTerminate = 0;
MyFreeLib(m_hinst);
m_hinst = 0;
return FALSE;
}
//**********************************************************************
// ISAPI Caching functions
//**********************************************************************
HINSTANCE CISAPICache::Load(PWSTR wszDLLName, CISAPI **ppISAPI, SCRIPT_TYPE st) {
DEBUG_CODE_INIT;
BOOL ret = FALSE;
PISAPINODE pTrav = NULL;
EnterCriticalSection(&m_CritSec);
for (pTrav = m_pHead; pTrav != NULL; pTrav = pTrav->m_pNext) {
if ( 0 == wcsicmp(pTrav->m_pISAPI->m_wszDLLName, wszDLLName)) {
DEBUGMSG(ZONE_ISAPI,(L"HTTPD: Found ISAPI dll in cache, name = %s, cur ref count = %d\r\n",
wszDLLName, pTrav->m_pISAPI->m_cRef));
break;
}
}
if (NULL == pTrav) {
DEBUGMSG(ZONE_ISAPI,(L"HTTPD: ISAPI dll name = %s not found in cache, creating new entry\r\n",wszDLLName));
if (NULL == (pTrav = MyAllocNZ(ISAPINODE)))
myleave(1200);
if (NULL == (pTrav->m_pISAPI = new CISAPI(st)))
myleave(1201);
if (NULL == (pTrav->m_pISAPI->m_wszDLLName = MySzDupW(wszDLLName)))
myleave(1202);
if (! pTrav->m_pISAPI->Load(wszDLLName))
myleave(1203);
pTrav->m_pNext = m_pHead;
m_pHead = pTrav;
}
pTrav->m_pISAPI->m_cRef++;
*ppISAPI = pTrav->m_pISAPI;
ret = TRUE;
done:
if (!ret) {
if (pTrav && pTrav->m_pISAPI) {
MyFree(pTrav->m_pISAPI->m_wszDLLName);
delete pTrav->m_pISAPI;
}
MyFree(pTrav);
}
DEBUGMSG_ERR(ZONE_ISAPI,(L"HTTPD: CISAPICache::LoadISAPI failed, err = %d, GLE = 0x%08x\r\n",err,GetLastError()));
LeaveCriticalSection(&m_CritSec);
if (ret)
return pTrav->m_pISAPI->m_hinst;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -