📄 soapisap.cpp
字号:
}
fRetVal = DllProcessAttach(g_hInstance);
CoUninitialize();
#endif
pVer->dwExtensionVersion = HSE_VERSION;
#ifndef UNDER_CE
lstrcpynA( pVer->lpszExtensionDesc, "MSSOAP Isapi Listener ", HSE_MAX_EXT_DLL_NAME_LEN );
#else
strncpy( pVer->lpszExtensionDesc, "MSSOAP Isapi Listener ", HSE_MAX_EXT_DLL_NAME_LEN );
#endif
EnterCriticalSection(&g_cs);
#ifdef UNDER_CE
if(NULL == g_hTerminateThread)
{
g_hTerminateThread = CreateThread(NULL, 0, TerminateISAPIThread, 0, 0, 0);
ASSERT(NULL != g_hTerminateThread);
g_hTerminateEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
ASSERT(NULL != g_hTerminateEvent);
}
#endif
if (!g_fThreadPoolInitialized)
{
if (InitializeThreadPool(g_cThreads, g_cObjCachePerThread) != 0)
{
fRetVal = FALSE;
goto Cleanup;
}
}
Cleanup:
++g_cExtensions;
LeaveCriticalSection(&g_cs);
if (!fRetVal)
{
TerminateExtension(0);
}
return fRetVal;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: TerminateExtension ( DWORD dwFlags )
//
// parameters:
// Arguments:
// dwFlags - specifies whether the DLL can refuse to unload or not
// Returns:
// TRUE, if the DLL can be unloaded
//
// description:
// This is optional ISAPI extension DLL entry point.
// If present, it will be called before unloading the DLL,
// giving it a chance to perform any shutdown procedures.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
BOOL WINAPI TerminateExtension ( DWORD dwFlags )
{
#ifdef UNDER_CE
DEBUGMSG(SOAP_ISAPI_DBG,(L"[SOAPISAPI] TerminateExtension--setting terminate event\n"));
SetEvent(g_hTerminateEvent);
#ifdef DEBUG
DWORD dwRet =
#endif
WaitForSingleObject(g_hTerminateEvent, INFINITE);
DEBUGMSG(SOAP_ISAPI_DBG,(L"[SOAPISAPI] --TerminateExtension--I'm awake, exiting\n"));
ASSERT(dwRet == WAIT_OBJECT_0);
#else
EnterCriticalSection(&g_cs);
if (--g_cExtensions == 0)
{
TerminateThreadPool();
}
LeaveCriticalSection(&g_cs);
#endif
return TRUE;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: HttpExtensionProc(EXTENSION_CONTROL_BLOCK *pECB)
//
// parameters:
// Arguments: pECB - pointer to the extenstion control block
//
// Returns: HSE_STATUS_PENDING on successful transmission completion
// HSE_STATUS_ERROR on failure
//
// description:
// Http extension proc called by the web server on request.
// Queue's up a request to the worker queue for async
// execution of the query.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD WINAPI HttpExtensionProc (EXTENSION_CONTROL_BLOCK *pECB )
{
if (g_pThreadPool->pWorkerQueue->dwSize < MAX_REQUEST_QUEUE_SIZE)
{
PWORKERITEM pItem = CreateWorkerItem(ProcessRequest, (void *)pECB);
if (pItem)
{
#ifdef UNDER_CE
//NOTE: we have to cache this because as soon as we put the
// WORKERITEM on the queue we lose ownership
HANDLE hProcessingHandle = pItem->hFinishedProcessing;
WorkerEnqueue(g_pThreadPool->pWorkerQueue, pItem);
DWORD dwRet = WaitForSingleObject(hProcessingHandle, INFINITE);
ASSERT(dwRet == WAIT_OBJECT_0);
if(NULL != hProcessingHandle)
CloseHandle(hProcessingHandle);
if(dwRet == WAIT_OBJECT_0)
{
BOOL fCanKeepAlive = FALSE;
//do a check to see if we CAN do a keepalive
pECB->ServerSupportFunction(pECB->ConnID,
HSE_REQ_IS_KEEP_CONN,
&fCanKeepAlive, NULL, NULL );
if(fCanKeepAlive)
return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
else
return HSE_STATUS_SUCCESS;
}
else
return HSE_STATUS_ERROR;
#else
WorkerEnqueue(g_pThreadPool->pWorkerQueue, pItem);
return HSE_STATUS_PENDING;
#endif
}
}
return HSE_STATUS_ERROR;
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: ProcessRequest(void * pContext)
//
// parameters:
// Arguments: pContext - pointer to the extenstion control block
//
// description:
// Process a query request, a callback called by a thread from
// the thread pool when a query is queued up by iis.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
DWORD ProcessRequest(void * pContext)
{
PREQUESTINFO pRequestInfo = (PREQUESTINFO)pContext;
PTHREADINFO pThreadInfo = (PTHREADINFO)pRequestInfo->m_pvThreadInfo;
EXTENSION_CONTROL_BLOCK *pECB = (EXTENSION_CONTROL_BLOCK*)pRequestInfo->m_pvContext;
HRESULT hr = S_OK;
CRequest cReq(pECB, pThreadInfo);
CRequest* pRequest = &cReq;
#ifndef UNDER_CE
HANDLE hRequestToken = NULL;
BOOL fImpersonate = FALSE;
#endif
CAutoBSTR bstrSoapAction;
TRACEL((2, (const LPCSTR) _T("Processing request: %S\r\n"), pECB->lpszQueryString));
#ifndef CE_NO_EXCEPTIONS
try
{
#endif
CHK (pRequest->Validate());
//
// Get the request token from IIS and set the token for this thread
//
#ifndef UNDER_CE
if(pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_GET_IMPERSONATION_TOKEN,
&hRequestToken,
NULL,
NULL
))
{
//
//Impersonate the logged on user
//
if (ImpersonateLoggedOnUser(hRequestToken))
fImpersonate = TRUE;
else
{
pRequest->SetErrorCode(Error_AccessDenied);
CHK(E_FAIL);
}
}
#endif
// We only process GET, POST or HEAD requests here
if(stricmp(pECB->lpszMethod, "POST"))
{
DEBUGMSG(SOAP_PROCESS_REQUEST,(L"[SOAPISAPI] got a POST\n"));
if (!stricmp(pECB->lpszMethod, "GET"))
{
hr = pRequest->ProcessGet(FALSE);
}
else if (!stricmp(pECB->lpszMethod, "HEAD"))
{
hr = pRequest->ProcessGet(TRUE);
}
else
{
pRequest->SetErrorCode(Error_MethodNotAllowed);
}
goto Cleanup;
}
// We only process POST from here on
if (FAILED(hr = pRequest->ProcessPathInfo()))
{
CHK (bstrSoapAction.Assign(pRequest->GetHeaderParam("SOAPAction"), FALSE));
pRequest->WriteFaultMessage(hr, bstrSoapAction);
goto Cleanup;
}
if (FAILED(hr = pRequest->ProcessParams()))
{
CHK (bstrSoapAction.Assign(pRequest->GetHeaderParam("SOAPAction"), FALSE));
pRequest->WriteFaultMessage(hr, bstrSoapAction);
goto Cleanup;
}
if (FAILED(hr = pRequest->ExecuteRequest()))
{
CHK (bstrSoapAction.Assign(pRequest->GetHeaderParam("SOAPAction"), FALSE));
pRequest->WriteFaultMessage(hr, bstrSoapAction);
goto Cleanup;
}
#ifndef UNDER_CE
}
catch (...)
{
ASSERT(0);
// We come here if we get an Access Violation. At this point we cannot trust any
// memory or cache in the thread. Just clear the thread's buffer and its
// cache.
// Don't try to release memory since it may be corrupted and cause further AVs.
if (pThreadInfo && pThreadInfo->pObjCache)
pThreadInfo->pObjCache->ClearCache();
pRequest->SetErrorCode(Error_InternalError);
}
#endif
Cleanup:
if(pRequest)
pRequest->FlushContents();
#ifndef UNDER_CE
if(fImpersonate)
{
//
// ReverToSelf() will set the security context to the IIS security Context
//
RevertToSelf();
}
pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_DONE_WITH_SESSION,
NULL,
NULL,
NULL
);
#endif
TRACEL((2, (const LPCSTR) _T("End Processing request")));
#ifdef UNDER_CE
ASSERT(NULL != pRequestInfo->hFinishedProcessing);
SetEvent(pRequestInfo->hFinishedProcessing);
#endif
//note: this return isnt used in CE
return HSE_STATUS_SUCCESS_AND_KEEP_CONN;
}
WCHAR g_wszThreadsRegKey[] = L"Software\\Microsoft\\MSSOAP\\SOAPISAP";
WCHAR g_wszThreadsParentRegKey[] = L"Software\\Microsoft\\MSSOAP";
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: InitRegInfo()
//
// parameters:
//
// description:
// Read the registry Software\\Microsoft\\MSSOAP\\SOAPISAP
// and get the number of threads.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void InitRegInfo()
{
HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
DWORD dwVal, dwLen = sizeof(DWORD);
if( (ERROR_SUCCESS != RegOpenKeyEx(HKEY_LOCAL_MACHINE, g_wszThreadsRegKey, 0,
KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
&hKey)) || hKey == INVALID_HANDLE_VALUE )
{
GetLastError();
return;
}
// Read num threads value.
if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"NumThreads", NULL, NULL, (LPBYTE) &dwVal, &dwLen))
{
g_cThreads = dwVal;
}
// Read num objs cahced per thread
dwLen = sizeof(DWORD);
if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"ObjCachedPerThread", NULL, NULL, (LPBYTE) &dwVal, &dwLen))
{
g_cObjCachePerThread = dwVal;
}
// Read max post size allowed
dwLen = sizeof(DWORD);
if(ERROR_SUCCESS == RegQueryValueEx(hKey, L"MaxPostSize", NULL, NULL, (LPBYTE) &dwVal, &dwLen))
{
g_cbMaxPost = dwVal;
}
#ifndef UNDER_CE
dwLen = sizeof(DWORD); //NOTE: setting dwLen was put in by chgray and was not in the
// orig STK2.2
if (RegQueryValueEx(hKey, L"NoNagling", NULL, NULL, (LPBYTE) &dwVal, &dwLen) == ERROR_SUCCESS)
{
g_dwNaglingFlags = dwVal ? HSE_IO_SYNC | HSE_IO_NODELAY : 0;
}
#endif
RegCloseKey(hKey);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: SetRegInfo()
//
// parameters:
//
// description:
// Initialize the registry Software\\Microsoft\\MSSOAP\\SOAPISAP
// and the number of threads.
//
/////////////////////////////////////////////////////////////////////////////////////////////////////////
void SetRegInfo()
{
HRESULT hr;
HKEY hKey = (HKEY) INVALID_HANDLE_VALUE;
DWORD dwVal, dwLen = 0;
if( (ERROR_SUCCESS != RegCreateKeyEx(HKEY_LOCAL_MACHINE, g_wszThreadsRegKey,
0, NULL, REG_OPTION_NON_VOLATILE,
KEY_SET_VALUE | KEY_QUERY_VALUE | KEY_ENUMERATE_SUB_KEYS,
NULL, &hKey, &dwVal)) || hKey == INVALID_HANDLE_VALUE )
{
GetLastError();
return;
}
//Read/set num threads value.
dwLen = sizeof(DWORD);
hr = RegQueryValueEx(hKey, L"NumThreads", NULL, NULL, (LPBYTE) &dwVal, &dwLen);
if (hr != ERROR_SUCCESS)
{
dwVal = (2 * g_si.dwNumberOfProcessors)+ 1;
dwLen = sizeof(DWORD);
hr = RegSetValueEx( hKey, L"NumThreads", NULL, REG_DWORD, (LPBYTE)&dwVal, dwLen);
}
dwLen = sizeof(DWORD);
hr = RegQueryValueEx(hKey, L"ObjCachedPerThread", NULL, NULL, (LPBYTE) &dwVal, &dwLen);
if(ERROR_SUCCESS != hr)
{
dwVal = 5; // default = 5 objects cached per thread
dwLen = sizeof(DWORD);
hr = RegSetValueEx( hKey, L"ObjCachedPerThread", NULL, REG_DWORD, (LPBYTE)&dwVal, dwLen);
}
dwLen = sizeof(DWORD);
hr = RegQueryValueEx(hKey, L"MaxPostSize", NULL, NULL, (LPBYTE) &dwVal, &dwLen);
if(ERROR_SUCCESS != hr)
{
dwVal = 100 * 1024; // default = 100 Kb.
dwLen = sizeof(DWORD);
hr = RegSetValueEx( hKey, L"MaxPostSize", NULL, REG_DWORD, (LPBYTE)&dwVal, dwLen);
}
dwLen = sizeof(DWORD);
if (RegQueryValueEx(hKey, L"NoNagling", NULL, NULL, (LPBYTE) &dwVal, &dwLen) != ERROR_SUCCESS)
{
dwVal = 0;
dwLen = sizeof(DWORD);
RegSetValueEx(hKey, L"NoNagling", NULL, REG_DWORD, (LPBYTE) &dwVal, dwLen);
}
RegCloseKey(hKey);
}
/////////////////////////////////////////////////////////////////////////////////////////////////////////
// function: RemoveRegInfo()
//
// parameters:
//
// description:
// Removes the registry Software\\Microsoft\\MSSOAP\\SOAPISAP
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -