Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2881 lines
92 KiB

/*++
Copyright (c) 2002 Microsoft Corporation
Module Name: Oca_Extension
Abstract: This Isapi extensions is used to provide a realtime interface
from the OCA web site and the Analysis Servers.
*/
//
// Includes
//
#include <windows.h>
#include <httpext.h>
#include <stdio.h>
#include <malloc.h>
#include <objbase.h>
#include <mqoai.h>
#include <mq.h>
#include <TCHAR.h>
#include <Rpcdce.h>
#include <strsafe.h>
#include <process.h>
#include <time.h>
#include <dbgeng.h> // for crdb.h
#include "messages.h"
#include "ErrorCodes.h"
#include "..\..\..\..\exts\extdll\crdb.h" // for source type definitions
typedef struct Isapi_Params
{
wchar_t OutQueueConStr1[MAX_PATH];
wchar_t OutQueueConStr2[MAX_PATH];
wchar_t InQueueConStr1[MAX_PATH];
// wchar_t InQueueConStr2[MAX_PATH];
TCHAR WatsonBaseDir[MAX_PATH]; // Watson server to get file from
TCHAR LocalBaseDir[MAX_PATH]; // Local machine directory to store dump file.
TCHAR LocalShareName[MAX_PATH];
TCHAR ErrorUrl[MAX_PATH];
TCHAR ManualUploadPath[MAX_PATH]; // Upload location for manual submissions
BOOL bAllowSR; // Process request of type CiSrcManualPssSr
} ISAPI_PARAMS, * PISAPIPARAMS;
/*
winnt.h:#define EVENTLOG_SUCCESS 0x0000
winnt.h:#define EVENTLOG_ERROR_TYPE 0x0001
winnt.h:#define EVENTLOG_WARNING_TYPE 0x0002
winnt.h:#define EVENTLOG_INFORMATION_TYPE 0x0004
winnt.h:#define EVENTLOG_AUDIT_SUCCESS 0x0008
winnt.h:#define EVENTLOG_AUDIT_FAILURE 0x0010
*/
typedef enum _ISAPI_EVENT_TYPE {
INFO = EVENTLOG_INFORMATION_TYPE,
WARN = EVENTLOG_WARNING_TYPE,
ERR = EVENTLOG_ERROR_TYPE,
SUCCESS = EVENTLOG_SUCCESS,
AUDIT_SUCCESS = EVENTLOG_AUDIT_SUCCESS,
AUDIT_FAIL = EVENTLOG_AUDIT_FAILURE
} ISAPI_EVENT_TYPE;
#define LOGLEVEL_ALWAYS 0x00001
#define LOGLEVEL_PERF 0x00100
#define LOGLEVEL_DEBUG 0x01000
#define LOGLEVEL_TRACE 0x10000
//
// Global Variables
//
TCHAR g_cszDefaultExtensionDll[] = _T("Oca_Extension.dll");
const int NUMBEROFPROPERTIES = 5;
long g_dwThreadCount = 0;
BOOL bInitialized = FALSE;
long MaxThreadCount = 100;
CRITICAL_SECTION SendCritSec;
ISAPI_PARAMS g_IsapiParams;
DWORD g_dwDebugMode = LOGLEVEL_ALWAYS;
DWORD g_dwProcessID = 0;
PSID g_psidUser = NULL;
HANDLE g_hEventSource = INVALID_HANDLE_VALUE;
HMODULE g_hModule = NULL;
TCHAR g_szAppName[MAX_PATH];
//
// Function Prototypes
//
unsigned int __stdcall WorkerFunction( void *vECB);
BOOL SendHttpHeaders(EXTENSION_CONTROL_BLOCK *, LPCSTR , LPCSTR, BOOL );
//HRESULT ConnectToMSMQ(QUEUEHANDLE *hQueue, wchar_t *QueueConnectStr, BOOL bSendAccess);
int GetRegData(PISAPIPARAMS pParams);
void LogEvent(DWORD dwLevel, ISAPI_EVENT_TYPE emType, DWORD dwEventID, DWORD dwErrorID, ...);
void LogEventWithString(DWORD dwLevel, ISAPI_EVENT_TYPE emType, DWORD dwEventID, LPCTSTR pFormat, ...);
DWORD SetupEventLog ( BOOL fSetup );
//
// Function Implementations.
//
BOOL WINAPI
GetExtensionVersion(
OUT HSE_VERSION_INFO *pVer
)
/*++
Purpose:
This is required ISAPI Extension DLL entry point.
Arguments:
pVer - points to extension version info structure
Returns:
always returns TRUE
--*/
{
HANDLE hToken;
TOKEN_USER *puser;
DWORD cb = 0;
DWORD dwResult = 0;
int *test = NULL;
free (test);
LogEventWithString(LOGLEVEL_TRACE, INFO, ISAPI_EVENT_DEBUG, "GetExtensionVersion()");
//
// tell the server our version number and extension description
//
ZeroMemory(&g_IsapiParams, sizeof ISAPI_PARAMS);
if (GetRegData (&g_IsapiParams))
bInitialized = TRUE;
else
bInitialized = FALSE;
SetupEventLog(TRUE);
InitializeCriticalSection(&SendCritSec);
pVer->dwExtensionVersion =
MAKELONG( HSE_VERSION_MINOR, HSE_VERSION_MAJOR );
g_dwProcessID = GetCurrentProcessId();
/*
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "GetExtensionVersion() - getting user SID");
if (OpenThreadToken(GetCurrentThread(), TOKEN_READ, TRUE, &hToken)
|| OpenProcessToken(GetCurrentProcess(), TOKEN_READ, &hToken))
{
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "GetExtensionVersion() - opened token");
GetTokenInformation(hToken, TokenUser, NULL, cb, &cb);
//puser = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, cb);
puser = (PTOKEN_USER)LocalAlloc(LPTR, cb);
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "GetExtensionVersion() - token requires %d bytes, puser = %08x", cb, (DWORD_PTR)puser);
if (puser && GetTokenInformation(hToken, TokenUser, puser, cb, &cb))
{
g_psidUser = puser->User.Sid;
//HeapFree(GetProcessHeap(), 0, (LPVOID)puser);
LocalFree(puser);
}
}
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "GetExtensionVersion() - got user SID");
*/
lstrcpyn(
pVer->lpszExtensionDesc,
"OCA Extension",
HSE_MAX_EXT_DLL_NAME_LEN
);
LogEvent(
LOGLEVEL_ALWAYS,
SUCCESS,
ISAPI_EVENT_SUCCESS_INITIALIZED,
ISAPI_M_SUCCESS_INITIALIZED
);
return TRUE;
}
BOOL ParseQueryString(
EXTENSION_CONTROL_BLOCK *pECB ,
TCHAR *FileName,
ULONG cbFileName,
int * piType,
TCHAR *szType,
ULONG cbType,
TCHAR *szSR,
ULONG cbSR
)
{
TCHAR *pFname = NULL;
TCHAR *pQueryString = NULL;
ULONG iCharCount = 0;
TCHAR *pType = NULL;
HRESULT hResult = S_OK;
BOOL fRetVal = FALSE;
LogEventWithString(
LOGLEVEL_TRACE,
INFO,
ISAPI_EVENT_TRACE,
"ParseQueryString(pECB, FileName=%s, *piType=%d, szType=%s)\r\n"
"pECB->lpszQueryString: %s",
FileName,
*piType,
szType,
pECB->lpszQueryString
);
pFname = FileName;
pQueryString = pECB->lpszQueryString;
//--> Parse the string if it does not exactly match the following format dump the string
//--> and send the client to the oca home page.
// The url we are parsing must have the following format:
/*
id=3_20_2002\62018831_2.cab&
Cab=/UploadBlue/62018831.cab&
AutoLaunch=1&
Client=BlueScreen&
Old=1&
BCCode=1000008e&
BCP1=C0000005&
BCP2=BFA00062&
BCP3=EF8AEAFC&
BCP4=00000000&
OSVer=5_1_2600&
SP=0_0&
Product=256_1&
LCID=1033
*/
if (*pQueryString == _T('\0'))
{
LogEventWithString(
LOGLEVEL_TRACE,
INFO,
ISAPI_EVENT_TRACE,
"ParseQueryString() - pQueryString is empty string"
);
goto ERRORS;
}
// first lets make sure the query string starts with id=
if ( ( (*pQueryString == _T('i')) || (*pQueryString == _T('I')) ) && (*(pQueryString +2) == _T('=')) )
{
ULONG cchFileName = cbFileName / sizeof(TCHAR);
// ok so far move past the = character.
pQueryString += 3;
//Now get the cab file name.
iCharCount = 0;
while ((*pQueryString != _T('&')) && (*pQueryString != _T('\0')) && (iCharCount < cchFileName -1 ))
{
*pFname = *pQueryString;
++pFname;
++pQueryString;
++ iCharCount;
// Null Terminate the fileName
}
FileName[cchFileName -1] = _T('\0');
if (*pQueryString != _T('\0'))
{
// now see what type of upload this is.
// Type = 5 is manual
// Type = 6 is stress
// Default is no type parameter and then the type is set to 0.
++ pQueryString;
if ( (*pQueryString == _T('T')) || (*pQueryString == _T('t')) )
{
while ( (*pQueryString != _T('\0')) && (*pQueryString != _T('e')) && (*pQueryString != _T('E')) )
{
++pQueryString;
}
if (*pQueryString != _T('\0'))
{
// We have the type parameter.
// now strip off the designator and save it in iType.
pType = szType;
*pType = _T(';');
++pType;
pQueryString+=2; // skip the e and the =
iCharCount = 0;
while ( (*pQueryString != _T('\0')) && (*pQueryString != _T('&')) && (iCharCount <3))
{
++iCharCount;
*pType = *pQueryString;
++pType;
++pQueryString;
}
// Null terminate the szType;
*pType = _T('\0');
pType = szType;
++pType; // skip the ;
*piType = atoi(pType);
}
else
{
// we ran into a problem set the type to 0
hResult = StringCbCopy(szType,cbType, _T(";1"));
*piType = 1;
if (FAILED (hResult))
{
goto ERRORS;
}
}
}
else
{
*piType = 1;
hResult = StringCbCopy(szType,cbType, _T(";1"));
if (FAILED (hResult))
{
goto ERRORS;
}
}
}
else
{
*piType = 1;
hResult = StringCbCopy(szType,cbType, _T(";1"));
if (FAILED (hResult))
{
goto ERRORS;
}
}
if (*pQueryString == _T('&') && *piType == CiSrcManualPssSr)
{
// Check if we have a SR attached in query string
if (!_tcsnicmp(pQueryString, _T("&SR="), 4))
{
// Copy the SR
if (cbSR != 0)
{
++pQueryString;
cbSR -= sizeof(TCHAR);
*szSR = _T(';');
}
while (*pQueryString != _T('\0') && *pQueryString != _T('&') &&
cbSR > sizeof(TCHAR))
{
*szSR = *pQueryString;
++szSR; ++pQueryString;
cbSR -= sizeof(TCHAR);
}
}
}
if (cbSR != 0)
{
*szSR = _T('\0');
}
fRetVal = TRUE;
}
ERRORS:
LogEventWithString(
LOGLEVEL_TRACE,
INFO,
ISAPI_EVENT_TRACE,
"Exiting ParseQueryString(pECB, FileName=%s, *piType=%d, szType=%s)\r\n"
"pQueryString: %s\r\n"
"fRetVal: %d\r\n",
FileName,
*piType,
szType,
pQueryString,
fRetVal
);
return fRetVal;
}
DWORD WINAPI
HttpExtensionProc(
IN EXTENSION_CONTROL_BLOCK *pECB
)
/*++
Purpose:
Create a thread to handle extended processing. It will be passed
the address of a function ("WorkerFunction") to run, and the address
of the ECB associated with this session.
Arguments:
pECB - pointer to the extenstion control block
Returns:
HSE_STATUS_PENDING to mark this request as pending
--*/
{
UINT dwThreadID;
HANDLE hThread;
//HANDLE hToken;
DWORD dwSize = 0;
TCHAR FinalURL[MAX_PATH];
TCHAR FileName[MAX_PATH];
int iType =1;
TCHAR szType [20];
TCHAR szSR [50];
char szHeader[] = "Content-type: text/html\r\n\r\n";
TCHAR ErrorText[255];
LogEventWithString(LOGLEVEL_TRACE, INFO, ISAPI_EVENT_TRACE, "HttpExtensionProc()");
ZeroMemory(ErrorText,sizeof ErrorText);
if (bInitialized)
{
if (g_dwThreadCount < MaxThreadCount)
{
hThread = NULL;
hThread = (HANDLE)_beginthreadex(NULL, // Pointer to thread security attributes
0, // Initial thread stack size, in bytes
&WorkerFunction, // Pointer to thread function
pECB, // The ECB is the argument for the new thread
0, // Creation flags
&dwThreadID // Pointer to returned thread identifier
);
//
// update global thread count
//
InterlockedIncrement( &g_dwThreadCount );
LogEventWithString(
LOGLEVEL_DEBUG,
SUCCESS,
ISAPI_EVENT_DEBUG,
"HttpExtensionProc() - started thread #%ld",
g_dwThreadCount
);
// Return HSE_STATUS_PENDING to release IIS pool thread without losing connection
if ((hThread) && (INVALID_HANDLE_VALUE != hThread))
{
CloseHandle(hThread);
return HSE_STATUS_PENDING;
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"HttpExtensionProc() - thread creation for thread #%ld failed",
g_dwThreadCount
);
}
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_PERF,
"HttpExtensionProc() - exceeded max thread count #%ld",
MaxThreadCount
);
}
if ( (!ParseQueryString(pECB, FileName, sizeof(FileName), &iType,
szType, sizeof(szType),
szSR, sizeof(szSR))) && (iType == 1) )
{
ZeroMemory (FinalURL,sizeof FinalURL);
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&State=0&Code=%d", g_IsapiParams.ErrorUrl,EXCEEDED_MAX_THREAD_COUNT) == S_OK)
{
LogEventWithString(
LOGLEVEL_DEBUG,
WARN,
ISAPI_EVENT_WARNING,
"HttpExtensionProc() - ParseQueryString() failed or iType=0\r\n"
"FileName: %s\r\n"
"iType: %d\r\n"
"szType%s\r\n"
"URL: %s",
FileName,
iType,
szType,
FinalURL
);
dwSize = (DWORD)_tcslen(FinalURL);
pECB->ServerSupportFunction(pECB->ConnID,
HSE_REQ_SEND_URL_REDIRECT_RESP,
FinalURL,
&dwSize,
NULL
);
// TODO: log event if error
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"HttpExtensionProc() - StringCbPrintf() failed"
);
// There is nothing we can do
return HSE_STATUS_ERROR;
}
}
else // Parsing succeeded
{
// Write the data to the client
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&State=0&Code=%d", g_IsapiParams.ErrorUrl, EXCEEDED_MAX_THREAD_COUNT) == S_OK)
{
LogEventWithString(
LOGLEVEL_TRACE,
SUCCESS,
ISAPI_EVENT_TRACE,
"HttpExtensionProc() - ParseQueryString() succeeded (debug), StringCbPrintf succeeded\r\n"
"FileName: %s\r\n"
"iType: %d\r\n"
"szType: %s\r\n"
"ErrorText: %s",
FileName,
iType,
szType,
ErrorText
);
}
else
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_ERROR,
"HttpExtensionProc() - ParseQueryString() succeeded (debug), StringCbPrintf failed\r\n"
"FileName: %s\r\n"
"iType: %d\r\n"
"szType: %s\r\n"
"ErrorText: %s",
FileName,
iType,
szType,
ErrorText
);
return HSE_STATUS_ERROR;
}
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&State=0&Code=%d", g_IsapiParams.ErrorUrl, EXCEEDED_MAX_THREAD_COUNT) == S_OK)
{
if (StringCbCat(FinalURL, sizeof FinalURL, ErrorText) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"HttpExtensionProc() - ParseQueryString() succeeded (debug), StringCbCat failed\r\n"
"FinalURL: %s\r\n"
"ErrorText: %s",
FinalURL,
ErrorText
);
return HSE_STATUS_ERROR;
}
LogEventWithString(
LOGLEVEL_DEBUG,
SUCCESS,
ISAPI_EVENT_DEBUG,
"HttpExtensionProc() - ParseQueryString() succeeded (debug), StringCbPrintf succeeded\r\n"
"URL: %s\r\n"
"iType: %d\r\n"
"szType: %s\r\n"
"ErrorText: %s",
FileName,
iType,
szType,
FinalURL
);
// We want to write the response url to the client
SendHttpHeaders( pECB, "200 OK", szHeader, FALSE );
dwSize = (DWORD)strlen( FinalURL );
pECB->WriteClient( pECB->ConnID, FinalURL, &dwSize, 0 );
// TODO: add event logging if error
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"HttpExtensionProc() - ParseQueryString() succeeded, StringCbPrintf failed\r\n"
"FinalURL: %s\r\n",
FinalURL
);
return HSE_STATUS_ERROR;
}
}
}
return HSE_STATUS_SUCCESS;
}
BOOL WINAPI
TerminateExtension(
IN DWORD dwFlags
)
/*++
Routine Description:
This function is called when the WWW service is shutdown.
Arguments:
dwFlags - HSE_TERM_ADVISORY_UNLOAD or HSE_TERM_MUST_UNLOAD
Return Value:
TRUE when extension is ready to be unloaded,
--*/
{
LogEventWithString(LOGLEVEL_TRACE, INFO, ISAPI_EVENT_TRACE, "TerminateExtension()");
//
// wait for all threads to terminate, sleeping for 1 sec
//
DWORD dwSize = 0;
if (dwFlags)
{
;
}
while( g_dwThreadCount > 0 )
{
SleepEx( 1000, FALSE );
}
// Delete the critical sections
DeleteCriticalSection(&SendCritSec);
//
// make sure the last thread indeed exited
//
SleepEx( 1000, FALSE );
LogEvent(LOGLEVEL_ALWAYS, SUCCESS, ISAPI_EVENT_SUCCESS_EXITING, ISAPI_M_SUCCESS_EXITING);
if (INVALID_HANDLE_VALUE != g_hEventSource)
{
DeregisterEventSource(g_hEventSource);
}
SetupEventLog(FALSE);
//Disconnect from queue's and db if necessary.
return TRUE;
}
BOOL GetRegData(PISAPIPARAMS pParams)
/*++
Routine Description:
This function is called when the WWW service is shutdown.
Arguments:
dwFlags - HSE_TERM_ADVISORY_UNLOAD or HSE_TERM_MUST_UNLOAD
Return Value:
TRUE when extension is ready to be unloaded,
--*/
{
HKEY hHKLM;
HKEY hExtensionKey;
BYTE Buffer[MAX_PATH * sizeof wchar_t];
DWORD Type;
DWORD BufferSize = MAX_PATH * sizeof wchar_t; // Set for largest value
LogEventWithString(LOGLEVEL_TRACE, INFO, ISAPI_EVENT_TRACE, "GetRegData()");
BOOL Status = FALSE;
if(!RegConnectRegistry(NULL, HKEY_LOCAL_MACHINE, &hHKLM))
{
if(!RegOpenKeyEx(hHKLM,_T("Software\\Microsoft\\OCA_EXTENSION"), 0, KEY_ALL_ACCESS, &hExtensionKey))
{
// Get the input queue directory path
if (RegQueryValueExW(hExtensionKey,L"OutgoingQueue1", 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
// LogEvent(_T("Failed to get InputQueue value from registry. Useing c:\\ as the default"));
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopyW (pParams->OutQueueConStr1,sizeof pParams->OutQueueConStr1, (wchar_t *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
// Get the input queue for full dumps
if (RegQueryValueExW(hExtensionKey,L"OutgoingQueue2", 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
// LogEvent(_T("Failed to get InputQueue value from registry. Useing c:\\ as the default"));
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopyW (pParams->OutQueueConStr2,sizeof pParams->OutQueueConStr2, (wchar_t *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
// Now get the Win2kDSN
if ( RegQueryValueExW(hExtensionKey,L"IncommingQueue1", 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS )
{
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopyW(pParams->InQueueConStr1,sizeof pParams->InQueueConStr1, (wchar_t *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
// Now get the Win2kDSN
if ( RegQueryValueEx(hExtensionKey,"ManualUploadPath", 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS )
{
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopy(pParams->ManualUploadPath,sizeof pParams->ManualUploadPath, (TCHAR*) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
// Get the input queue directory path
/* if (RegQueryValueExW(hExtensionKey,L"OutgoingQueue2", 0, &Type, Buffer, &BufferSize) != ERROR_SUCCESS)
{
// LogEvent(_T("Failed to get InputQueue value from registry. Useing c:\\ as the default"));
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopyW (pParams->OutQueueConStr2,sizeof pParams->OutQueueConStr2, (wchar_t *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
*/
// Now get the Win2kDSN
/* if ( RegQueryValueExW(hExtensionKey,L"IncommingQueue2", 0, &Type, Buffer, &BufferSize))
{
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopyW(pParams->InQueueConStr2,sizeof pParams->InQueueConStr2, (wchar_t *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
*/ // Now get the Win2kDSN
if ( RegQueryValueEx(hExtensionKey,_T("WatsonBaseDir"), 0, &Type, Buffer, &BufferSize))
{
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopy(pParams->WatsonBaseDir,sizeof pParams->WatsonBaseDir, (TCHAR *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
if ( RegQueryValueEx(hExtensionKey,_T("LocalBaseDir"), 0, &Type, Buffer, &BufferSize))
{
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopy(pParams->LocalBaseDir,sizeof pParams->LocalBaseDir,(TCHAR *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
if ( RegQueryValueEx(hExtensionKey,_T("LocalShareName"), 0, &Type, Buffer, &BufferSize))
{
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopy(pParams->LocalShareName,sizeof pParams->LocalShareName, (TCHAR *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
if ( RegQueryValueEx(hExtensionKey,_T("MaxThreadCount"), 0, &Type, Buffer, &BufferSize))
{
Status = FALSE;
goto ERROR1;
}
else
{
MaxThreadCount = *((long*)Buffer);
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
if ( RegQueryValueEx(hExtensionKey,_T("AllowSR"), 0, &Type, Buffer, &BufferSize))
{
pParams->bAllowSR = FALSE;
}
else
{
pParams->bAllowSR = *((BOOL*)Buffer);
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
if ( RegQueryValueEx(hExtensionKey,_T("Debug"), 0, &Type, Buffer, &BufferSize))
{
Status = FALSE;
goto ERROR1;
}
else
{
g_dwDebugMode = *((DWORD*)Buffer);
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
if ( RegQueryValueEx(hExtensionKey,_T("ErrorUrl"), 0, &Type, Buffer, &BufferSize))
{
Status = FALSE;
goto ERROR1;
}
else
{
if (StringCbCopy(g_IsapiParams.ErrorUrl,sizeof g_IsapiParams.ErrorUrl, (TCHAR *) Buffer) != S_OK)
{
Status = FALSE;
goto ERROR1;
}
BufferSize = MAX_PATH * sizeof wchar_t;
ZeroMemory(Buffer, BufferSize);
}
RegCloseKey(hExtensionKey);
RegCloseKey(hHKLM);
return TRUE;
}
else
{
RegCloseKey(hHKLM);
return FALSE;
}
}
else
{
return FALSE;
}
ERROR1:
if (hExtensionKey)
RegCloseKey(hExtensionKey);
if (hHKLM)
RegCloseKey(hHKLM);
LogEventWithString(LOGLEVEL_TRACE, INFO, ISAPI_EVENT_TRACE, "Exiting GetRegData()\r\nreturn value: %d", (int)Status);
return Status;
}
BOOL SendQueueMessage(QUEUEHANDLE hOutgoingQueue, wchar_t *MessageGuid, wchar_t *FilePath)
{
MQMSGPROPS msgProps;
MSGPROPID aMsgPropId[NUMBEROFPROPERTIES];
MQPROPVARIANT aMsgPropVar[NUMBEROFPROPERTIES];
HRESULT aMsgStatus[NUMBEROFPROPERTIES];
DWORD cPropId = 0;
BOOL Status = TRUE;
HRESULT hResult = S_OK;
char szGuid[512];
char szPath[512];
LogEventWithString(LOGLEVEL_TRACE, INFO, ISAPI_EVENT_TRACE, "SendQueueMessage()");
if ( (!MessageGuid ) || (!FilePath))
{
wcstombs( szGuid, MessageGuid, sizeof(MessageGuid)/sizeof(MessageGuid[0]) );
wcstombs( szPath, FilePath, sizeof(FilePath)/sizeof(FilePath[0]) );
LogEvent(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR_INVALID_SEND_PARAMS,
ISAPI_M_ERROR_INVALID_SEND_PARAMS,
(MessageGuid != NULL) ? szGuid : _T(""),
(FilePath != NULL) ? szPath : _T("")
);
Status = FALSE;
}
else
{
aMsgPropId [cPropId] = PROPID_M_LABEL; // Property ID.
aMsgPropVar[cPropId].vt = VT_LPWSTR; // Type indicator.
aMsgPropVar[cPropId].pwszVal = MessageGuid; // The message label.
cPropId++;
aMsgPropId [cPropId] = PROPID_M_BODY;
aMsgPropVar [cPropId].vt = VT_VECTOR|VT_UI1;
aMsgPropVar [cPropId].caub.pElems = (LPBYTE) FilePath;
aMsgPropVar [cPropId].caub.cElems = (DWORD) wcslen(FilePath)* 2;
cPropId++;
aMsgPropId [cPropId] = PROPID_M_BODY_TYPE;
aMsgPropVar[cPropId].vt = VT_UI4;
aMsgPropVar[cPropId].ulVal = (DWORD) VT_BSTR;
cPropId++;
// Initialize the MQMSGPROPS structure.
msgProps.cProp = cPropId;
msgProps.aPropID = aMsgPropId;
msgProps.aPropVar = aMsgPropVar;
msgProps.aStatus = aMsgStatus;
//
// Send it
//
hResult = MQSendMessage(
hOutgoingQueue, // Queue handle.
&msgProps, // Message property structure.
MQ_NO_TRANSACTION // No transaction.
);
if (FAILED(hResult))
{
wcstombs(szGuid,MessageGuid, wcslen(MessageGuid) *2);
wcstombs(szPath,FilePath, wcslen(FilePath) *2);
LogEvent(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR_CANNOT_SEND,
ISAPI_M_ERROR_CANNOT_SEND,
szGuid,
szPath,
hResult
);
Status = FALSE;
}
}
LogEventWithString(
LOGLEVEL_TRACE,
INFO,
ISAPI_EVENT_TRACE,
"Exiting SendQueueMessage()\r\n"
"return value: %d",
(int)Status
);
return Status;
}
unsigned int __stdcall
WorkerFunction(
void *vECB
)
/*++
Purpose:
This Function performs all of the Message queueing for realtime processing
with out tying up the IIS process threads.
Arguments:
vECB - points to current extension control block
Returns:
returns 0
--*/
{
char szHeader[] = "Content-type: text/html\r\n\r\n";
EXTENSION_CONTROL_BLOCK *pECB;
HRESULT hResult = S_OK;
GUID MessageGuid;
TCHAR DestinationDir[MAX_PATH];
TCHAR *pQueryString = NULL;
TCHAR *pFname = NULL;
TCHAR CurrentFileName[MAX_PATH];
TCHAR SourceDir[MAX_PATH];
HANDLE hToken = INVALID_HANDLE_VALUE;
wchar_t wszMessageGuid[100];
TCHAR szMessageGuid[200];
wchar_t *szTempMessageGuid = NULL;
DWORD dwSize = 0;
wchar_t DestinationPath[MAX_PATH];
wchar_t RecMessageBody[255];
TCHAR szRecMessageBody[255];
UINT RetryCount = 0;
BOOL Status = TRUE;
BOOL bReadFromPrimary = TRUE;
int ErrorCode = 0;
TCHAR *temp = NULL;
TCHAR RedirURL[MAX_PATH];
DWORD dwDestSize = 0;
TCHAR szType[10];
TCHAR szSR[50];
int iCharCount = 0;
TCHAR *pType = NULL;
int iType = 1;
TCHAR FinalURL[MAX_PATH];
int iState = 0;
wchar_t *temp2 = NULL;
HANDLE hManualFile = INVALID_HANDLE_VALUE;
TCHAR TestDestination[MAX_PATH];
DWORD CharCount = 0;
TCHAR ErrorText[255];
TCHAR PerfText[MAX_PATH];
// Recieve message vars
MSGPROPID PropIds[5];
MQPROPVARIANT PropVariants[5];
HRESULT hrProps[5];
MQMSGPROPS MessageProps;
DWORD i = 0;
wchar_t RecLabel[100];
wchar_t LocalRecBody[255];
DWORD RecMessageBodySize = sizeof LocalRecBody;
DWORD RecLabelLength = sizeof RecLabel;
HANDLE hCursor = INVALID_HANDLE_VALUE;
BOOL MessageFound = FALSE;
time_t Start;
time_t Stop;
DWORD StartSendQueue = 0, StopSendQueue = 0;
DWORD StartRecvQueue = 0, StopRecvQueue = 0;
DWORD StartThread= 0, StopThread = 0;
DWORD ElapsedTimeThread = 0, ElapsedTimeSendQueue = 0, ElapsedTimeRecvQueue;
BOOL CursorValid = FALSE;
BOOL fFullDump = FALSE;
StartThread = GetTickCount();
// Queue Handles
QUEUEHANDLE hPrimaryInQueue = NULL;
QUEUEHANDLE hPrimaryOutQueue = NULL;
// QUEUEHANDLE hSecondaryInQueue = NULL;
// QUEUEHANDLE hSecondaryOutQueue = NULL;
LogEventWithString(
LOGLEVEL_DEBUG,
INFO,
ISAPI_EVENT_DEBUG,
"WorkerFunction()\r\n"
"Last Error: %08x\r\n"
"TID: %ld\r\n",
GetLastError(),
GetCurrentThreadId()
);
// Clear the strings
ZeroMemory(DestinationPath, sizeof DestinationPath);
ZeroMemory(RecMessageBody, sizeof RecMessageBody);
ZeroMemory(szMessageGuid, sizeof szMessageGuid);
ZeroMemory(RedirURL, sizeof RedirURL);
ZeroMemory(FinalURL, sizeof FinalURL);
ZeroMemory(wszMessageGuid, sizeof wszMessageGuid);
ZeroMemory(DestinationDir, sizeof DestinationDir);
ZeroMemory(TestDestination, sizeof TestDestination);
ZeroMemory(ErrorText, sizeof ErrorText);
ZeroMemory(PerfText, sizeof PerfText);
ZeroMemory(CurrentFileName, sizeof CurrentFileName);
ZeroMemory(SourceDir, sizeof SourceDir);
ZeroMemory(szRecMessageBody, sizeof szRecMessageBody);
ZeroMemory(szType, sizeof szType);
//
// Initialize local ECB pointer to void pointer passed to thread
//
LogEventWithString(
LOGLEVEL_DEBUG,
INFO,
ISAPI_EVENT_DEBUG,
"WorkerFunction()\r\n"
"Calling pECB->ServerSupportFunction\r\n"
"Last Error: %08lx",
GetLastError()
);
pECB = (EXTENSION_CONTROL_BLOCK *)vECB;
Status = pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_GET_IMPERSONATION_TOKEN,
&hToken,
NULL,
NULL
);
LogEventWithString(
LOGLEVEL_DEBUG,
INFO,
ISAPI_EVENT_DEBUG,
"WorkerFunction()\r\n"
"Called pECB->ServerSupportFunction\r\n"
"Status: %d\r\n"
"hToken: %08x\r\n"
"Last Error: %08lx",
Status,
(DWORD_PTR)hToken,
GetLastError()
);
// TODO: handle error if returned
if ( !ImpersonateLoggedOnUser(hToken))
{
// We failed to impersonate the user. We Cannot continue.
LogEvent(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR_CANT_IMPERSONATE,
ISAPI_M_ERROR_CANT_IMPERSONATE,
GetLastError()
);
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"), FAILED_TO_IMPERSONATE_USER) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf() failed\r\n"
"hToken: %08x\r\n",
(DWORD_PTR)hToken
);
}
goto ERRORS;
}
//
//Get filename from parameter list.
//
ZeroMemory (CurrentFileName,sizeof CurrentFileName);
//
// Get the file name from the query string.
//
if ( (!ParseQueryString(pECB, CurrentFileName, sizeof(CurrentFileName), &iType,
szType, sizeof(szType),
szSR, sizeof(szSR)) ))
{
LogEventWithString(
LOGLEVEL_ALWAYS,
WARN,
ISAPI_EVENT_WARNING,
"WorkerFunction() - ParseQueryString() failed\r\n"
"CurrentFileName: %s\r\n"
"iType: %d\r\n"
"szType%s",
CurrentFileName,
iType,
szType
);
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"),FAILED_TO_PARSE_QUERYSTRING ) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf() failed"
);
}
goto ERRORS;
}
LogEventWithString(
LOGLEVEL_DEBUG,
INFO,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - ParseQueryString() succeeded\r\n"
"CurrentFileName: %s\r\n"
"iType: %d\r\n"
"szType%s",
CurrentFileName,
iType,
szType
);
//
// Copy File Localy
// Note this needs to be removed when the client uploads the file
// Directly to our servers.
//
// build the source file name.
switch (iType)
{
case CiSrcErClient:
if (StringCbPrintf(SourceDir,sizeof SourceDir, _T("%s\\%s"), g_IsapiParams.WatsonBaseDir, CurrentFileName) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf() failed"
);
Status = FALSE;
goto ERRORS;
}
/* if (StringCbPrintf(DestinationDir,sizeof DestinationDir, _T("%s\\%s"), g_IsapiParams.LocalBaseDir,CurrentFileName) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf() failed"
);
Status = FALSE;
goto ERRORS;
}
*/
break;
case CiSrcManualFullDump:
fFullDump = TRUE;
iType = CiSrcManual;
if (StringCbPrintf(szType, sizeof(szType), _T(";%ld"), iType) != S_OK)
{
// Failure is harmless, debugger will consider these 2 types as the same
iType = CiSrcManualFullDump;
}
// fall through
case CiSrcCER:
case CiSrcManual:
case CiSrcStress:
break;
case CiSrcManualPssSr:
fFullDump = TRUE; // we want to process these same way as fulldumps
break;
default: // invalid type specified
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"),INVALID_TYPE_SPECIFIED) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf() failed"
);
}
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - unknown iType specified\r\n"
"iType: %d",
iType
);
goto ERRORS;
}
// Now change the date file name \ to an _ note this only works for the date\filename format
/* if ((iType != 5) && (iType != 6))
{
dwDestSize = (DWORD) _tcslen(DestinationDir);
if (dwDestSize >0)
{
temp = DestinationDir + _tcslen(DestinationDir);
while ((*temp != '\\') && (*temp != '/'))
-- temp;
if ((*temp == '\\') || (*temp == '/'))
*temp = '_';
}
else
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - dwDestSize = 0"
);
Status = FALSE;
goto ERRORS;
}
if (!CopyFile (SourceDir, DestinationDir, FALSE) )
{
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"),FAILED_TO_COPY_FILE) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf() failed"
);
}
LogEvent(LOGLEVEL_ALWAYS, WARN, ISAPI_EVENT_WARNING_FILE_COPY_FAILED, ISAPI_M_WARNING_FILE_COPY_FAILED, SourceDir, DestinationDir, GetLastError());
Status = FALSE;
goto ERRORS;
}
}
*/
//ZeroMemory (DestinationDir, sizeof DestinationDir);
/*
if ((iType != 5) && (iType != 6))
{
if (_tcslen(CurrentFileName) > 0)
{
temp = CurrentFileName + _tcslen(CurrentFileName);
while ( (*temp != '\\') && (*temp != '/') && (temp!= CurrentFileName) )
-- temp;
if ((*temp == '\\') || (*temp == '/'))
*temp = '_';
}
else
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - _tcslen(CurrentFileName) = 0"
);
Status = FALSE;
goto ERRORS;
}
}
*/
switch (iType)
{
case CiSrcErClient:
if (StringCbPrintf(DestinationDir, sizeof DestinationDir, _T("%s\\%s%s"), g_IsapiParams.WatsonBaseDir, CurrentFileName,szType)!= S_OK)
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - StringCbPrintf failed"
);
Status = FALSE;
goto ERRORS;
}
break;
case CiSrcManualFullDump: // Same as 5 but a full dump, send it off to a separate Q dedicated to fulldumps
iType = CiSrcManual;
// fall through
case CiSrcManualPssSr:
fFullDump = TRUE;
// fall through
case CiSrcCER:
case CiSrcManual:
case CiSrcStress:
if ((iType == CiSrcManualPssSr) && g_IsapiParams.bAllowSR)
{
hResult = StringCbPrintf(DestinationDir, sizeof DestinationDir, _T("%s\\%s%s;%s"),
g_IsapiParams.ManualUploadPath,CurrentFileName,szType,szSR);
} else
{
hResult = StringCbPrintf(DestinationDir, sizeof DestinationDir, _T("%s\\%s%s"),
g_IsapiParams.ManualUploadPath,CurrentFileName,szType);
}
if (hResult != S_OK)
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - StringCbPrintf failed"
);
Status = FALSE;
goto ERRORS;
}
else
{
// Check to see if the file exists
//
if (StringCbPrintf(TestDestination, sizeof TestDestination,_T("%s\\%s"), g_IsapiParams.ManualUploadPath,CurrentFileName)== S_OK)
{
hManualFile = CreateFile(TestDestination,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hManualFile == INVALID_HANDLE_VALUE)
{
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"),FILE_NOT_FOUND) != S_OK)
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - StringCbPrintf failed"
);
}
LogEvent(LOGLEVEL_ALWAYS, WARN, ISAPI_EVENT_WARNING_FILE_MISSING, ISAPI_M_WARNING_FILE_MISSING, TestDestination);
Status = FALSE;
goto ERRORS;
}
else
{
CloseHandle(hManualFile);
}
}
else
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - StringCbPrintf failed"
);
Status = FALSE;
goto ERRORS;
}
}
break;
#ifdef USE_OLD_STRESS_SOURCE
case 6:
if (StringCbPrintf(DestinationDir, sizeof DestinationDir, _T("%s%s"), CurrentFileName,szType)!= S_OK)
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - StringCbPrintf failed"
);
Status = FALSE;
goto ERRORS;
}
else
{
hManualFile = CreateFile(TestDestination,GENERIC_READ,FILE_SHARE_READ,NULL,OPEN_EXISTING,FILE_ATTRIBUTE_NORMAL,NULL);
if (hManualFile == INVALID_HANDLE_VALUE)
{
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"),FILE_NOT_FOUND) != S_OK)
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - StringCbPrintf failed"
);
}
LogEvent(LOGLEVEL_ALWAYS, WARN, ISAPI_EVENT_WARNING_FILE_MISSING, ISAPI_M_WARNING_FILE_MISSING, TestDestination);
Status = FALSE;
goto ERRORS;
}
else
{
CloseHandle(hManualFile);
}
}
break;
#endif // USE_OLD_STRESS_SOURCE
default: // Invalid Type
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - unknown iType specified\r\n"
"iType: %d",
iType
);
goto ERRORS;
}
ZeroMemory (DestinationPath, sizeof DestinationPath);
mbstowcs(DestinationPath,DestinationDir,_tcslen(DestinationDir));
//
// Generate Guid for this message
//
hResult = CoCreateGuid(&MessageGuid);
if (FAILED(hResult))
{
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"),FAILED_TO_CREATE_GUID) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
}
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - CoCreateGuid failed\r\n"
"hResult: %08x",
hResult
);
goto ERRORS;
}
else
{
hResult = UuidToStringW(&MessageGuid, &szTempMessageGuid);
if (hResult == RPC_S_OK)
{
// Make a copy of the string quid then release it.
if (StringCbCopyW(wszMessageGuid,sizeof wszMessageGuid, szTempMessageGuid) != S_OK)
{
LogEvent(LOGLEVEL_ALWAYS, ERR, ISAPI_EVENT_ERROR_GUID_COPY, ISAPI_M_ERROR_GUID_COPY, szTempMessageGuid, wszMessageGuid, GetLastError());
goto ERRORS;
}
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - UuidToStringW failed\r\n"
"hResult: %08x\r\n"
"szTempMessageGuid: %s",
hResult,
szTempMessageGuid
);
// TODO: goto ERRORS?
}
}
//EnterCriticalSection(&SendCritSec);
StartSendQueue = GetTickCount();
// if connect to primary Receive
hResult = MQOpenQueue(g_IsapiParams.InQueueConStr1,
MQ_RECEIVE_ACCESS,
MQ_DENY_NONE,
&hPrimaryInQueue);
if (SUCCEEDED(hResult))
{
hResult = MQOpenQueue( (fFullDump ? g_IsapiParams.OutQueueConStr2 : g_IsapiParams.OutQueueConStr1),
MQ_SEND_ACCESS,
MQ_DENY_NONE,
&hPrimaryOutQueue);
if (SUCCEEDED(hResult))
{
EnterCriticalSection(&SendCritSec);
if( SendQueueMessage(hPrimaryOutQueue, wszMessageGuid, DestinationPath))
{
LogEventWithString(
LOGLEVEL_TRACE,
SUCCESS,
ISAPI_EVENT_TRACE,
"WorkerFunction() - SendQueueMessage() succeeded - using PrimaryOutQueue\r\n"
"hPrimaryOutQueue: %08x\r\n"
"wszMessageGuid: %s\r\n"
"DestinationPath: %s",
(DWORD_PTR)hPrimaryOutQueue,
wszMessageGuid,
DestinationPath
);
LeaveCriticalSection(&SendCritSec);
bReadFromPrimary = TRUE;
MQCloseQueue(hPrimaryOutQueue);
hPrimaryOutQueue = NULL;
}
else
{
LeaveCriticalSection(&SendCritSec);
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - SendQueueMessage() failed\r\n"
"hPrimaryOutQueue: %08x\r\n"
"wszMessageGuid: %s\r\n"
"DestinationPath: %s",
(DWORD_PTR)hPrimaryOutQueue,
wszMessageGuid,
DestinationPath
);
MQCloseQueue(hPrimaryInQueue);
MQCloseQueue(hPrimaryOutQueue);
goto ERRORS;
// This block is commented out because each web server now only has 1 message queue
/*
hResult = MQOpenQueue(g_IsapiParams.InQueueConStr2,
MQ_RECEIVE_ACCESS,
MQ_DENY_NONE,
&hPrimaryInQueue);
if (SUCCEEDED(hResult))
{
hResult = MQOpenQueue(g_IsapiParams.OutQueueConStr2,
MQ_SEND_ACCESS,
MQ_DENY_NONE,
&hSecondaryInQueue);
if (SUCCEEDED(hResult))
{
EnterCriticalSection(&SendCritSec);
if( SendQueueMessage(hSecondaryOutQueue, wszMessageGuid, DestinationPath))
{
LeaveCriticalSection(&SendCritSec);
bReadFromPrimary = FALSE;
MQCloseQueue(hPrimaryOutQueue);
hPrimaryOutQueue = NULL;
}
else
{
LeaveCriticalSection(&SendCritSec);
MQCloseQueue(hSecondaryInQueue);
MQCloseQueue(hSecondaryOutQueue);
hSecondaryInQueue = NULL;
hSecondaryOutQueue = NULL;
goto ERRORS;
}
}
else
{
MQCloseQueue(hSecondaryInQueue);
hSecondaryInQueue = NULL;
goto ERRORS;
}
}
else
{
goto ERRORS;
}
*/
}
}
else // MQOpenQueue(g_IsapiParams.OutQueueConStr1,
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - MQOpenQueue(g_IsapiParams.OutQueueConStr1 ...) failed"
"hResult: %08x",
hResult
);
// This block is commented out because each web server now only has 1 message queue
/* MQCloseQueue(hPrimaryInQueue);
hResult = MQOpenQueue(g_IsapiParams.InQueueConStr2,
MQ_RECEIVE_ACCESS,
MQ_DENY_NONE,
&hPrimaryInQueue);
if (SUCCEEDED(hResult))
{
hResult = MQOpenQueue(g_IsapiParams.OutQueueConStr2,
MQ_SEND_ACCESS,
MQ_DENY_NONE,
&hSecondaryInQueue);
if (SUCCEEDED(hResult))
{
EnterCriticalSection(&SendCritSec);
if( SendQueueMessage(hSecondaryOutQueue, wszMessageGuid, DestinationPath))
{
LeaveCriticalSection(&SendCritSec);
bReadFromPrimary = FALSE;
MQCloseQueue(hPrimaryOutQueue);
hPrimaryOutQueue = NULL;
}
else
{
LeaveCriticalSection(&SendCritSec);
MQCloseQueue(hSecondaryInQueue);
MQCloseQueue(hSecondaryOutQueue);
hSecondaryInQueue = NULL;
hSecondaryOutQueue = NULL;
goto ERRORS;
}
}
else
{
MQCloseQueue(hSecondaryInQueue);
hSecondaryInQueue = NULL;
goto ERRORS;
}
}
else
{
goto ERRORS;
}
*/
goto ERRORS;
}
}
else // MQOpenQueue(g_IsapiParams.InQueueConStr1,
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - MQOpenQueue(g_IsapiParams.InQueueConStr1 ...) failed"
"hResult: %08x",
hResult
);
// This block is commented out because each web server now only has 1 message queue
/* hResult = MQOpenQueue(g_IsapiParams.InQueueConStr2,
MQ_RECEIVE_ACCESS,
MQ_DENY_NONE,
&hPrimaryInQueue);
if (SUCCEEDED(hResult))
{
hResult = MQOpenQueue(g_IsapiParams.OutQueueConStr2,
MQ_SEND_ACCESS,
MQ_DENY_NONE,
&hSecondaryInQueue);
if (SUCCEEDED(hResult))
{
EnterCriticalSection(&SendCritSec);
if( SendQueueMessage(hSecondaryOutQueue, wszMessageGuid, DestinationPath))
{
LeaveCriticalSection(&SendCritSec);
bReadFromPrimary = FALSE;
MQCloseQueue(hPrimaryOutQueue);
hPrimaryOutQueue = NULL;
}
else
{
LeaveCriticalSection(&SendCritSec);
MQCloseQueue(hSecondaryInQueue);
MQCloseQueue(hSecondaryOutQueue);
hSecondaryInQueue = NULL;
hSecondaryOutQueue = NULL;
goto ERRORS;
}
}
else
{
MQCloseQueue(hSecondaryInQueue);
hSecondaryInQueue = NULL;
goto ERRORS;
}
}
else
{
goto ERRORS;
}
*/
goto ERRORS;
}
StopSendQueue = GetTickCount();
//-------------------------------------------------------------------------------------------------
// Recieve the response from kd
//-------------------------------------------------------------------------------------------------
Sleep(1000); // give kd a chance to process the message.
Status = FALSE;
ZeroMemory(LocalRecBody,sizeof LocalRecBody);
ZeroMemory(RecLabel,sizeof RecLabel);
i = 0;
PropIds[i] = PROPID_M_LABEL_LEN;
PropVariants[i].vt = VT_UI4;
PropVariants[i].ulVal = RecLabelLength;
i++;
PropIds[i] = PROPID_M_LABEL;
PropVariants[i].vt = VT_LPWSTR;
PropVariants[i].pwszVal = RecLabel;
i++;
MessageProps.aPropID = PropIds;
MessageProps.aPropVar = PropVariants;
MessageProps.aStatus = hrProps;
MessageProps.cProp = i;
double TotalElapsedTime = 0.0;
StartRecvQueue = GetTickCount();
if ( (hResult = MQCreateCursor( /*(bReadFromPrimary == TRUE) ? */hPrimaryInQueue ,//: hSecondaryInQueue,
&hCursor))
!= S_OK)
{
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"), FAILED_TO_CREATE_CURSOR)!= S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
}
LogEvent(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR_CANNOT_CREATE_RECEIVE_CURSOR,
ISAPI_M_ERROR_CANNOT_CREATE_RECEIVE_CURSOR,
hResult,
(DWORD_PTR)hCursor
);
Status = FALSE;
goto ERRORS;
}
else
{
do {
CursorValid = TRUE;
// dwSize = _tcslen(_T("Starting Scan <BR>"));
// pECB->WriteClient(pECB->ConnID,_T("Starting Scan <BR>"),&dwSize,0);
// Peak at each member of the queue and return the label.
time(&Start);
hResult = MQReceiveMessage(/*(bReadFromPrimary == TRUE) ? */hPrimaryInQueue,// : hSecondaryInQueue, // Queue handle.
20000, // Maximum time (msec) to read the message.
MQ_ACTION_PEEK_CURRENT, // Receive action.
&MessageProps, // Message property structure.
NULL, // No OVERLAPPED structure.
NULL, // No callback function.
hCursor, // Cursor handle.
NULL // No transaction.
);
time(&Stop);
TotalElapsedTime+= difftime(Stop,Start);
if (hResult == S_OK)
{
MessageFound = FALSE;
// There is a message in the queue.
// now see if it is the one we want.
// if the message was found retrieve it.
// Otherwise close the cursor and return false.
do
{
if (! _wcsicmp(RecLabel,wszMessageGuid))
{
MessageFound = TRUE;
}
else
{
// Not it Lets peek at the next one
time(&Start);
PropVariants[i].ulVal = RecLabelLength; // Reset the label buffer size.
hResult = MQReceiveMessage(/*(bReadFromPrimary == TRUE) ?*/ hPrimaryInQueue,// : hSecondaryInQueue, // Queue handle.
((DWORD)(20.0 - TotalElapsedTime)) * 1000, // Maximum time (msec).
MQ_ACTION_PEEK_NEXT, // Receive action.
&MessageProps, // Message property structure.
NULL, // No OVERLAPPED structure.
NULL, // No callback function.
hCursor, // Cursor handle.
NULL // No transaction.
);
time(&Stop);
TotalElapsedTime += difftime(Stop, Start);
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - MQReceiveMessage(hPrimaryInQueue ...) failed (peek)\r\n"
"hResult: %08x",
hResult
);
}
} while ( (!MessageFound ) && (hResult == S_OK) && (TotalElapsedTime < 20.0));
if (!MessageFound)
{
Status = FALSE;
}
if (MessageFound)
{
// retrieve the current message
i = 0;
PropIds[i] = PROPID_M_LABEL_LEN;
PropVariants[i].vt = VT_UI4;
PropVariants[i].ulVal = RecLabelLength;
i++;
PropIds[i] = PROPID_M_LABEL;
PropVariants[i].vt = VT_LPWSTR;
PropVariants[i].pwszVal = RecLabel;
i++;
PropIds[i] = PROPID_M_BODY_SIZE;
PropVariants[i].vt = VT_UI4;
i++;
PropIds[i] = PROPID_M_BODY_TYPE;
PropVariants[i].vt = VT_UI4;
i++;
PropIds[i] = PROPID_M_BODY;
PropVariants[i].vt = VT_VECTOR|VT_UI1;
PropVariants[i].caub.pElems = (LPBYTE) LocalRecBody;
PropVariants[i].caub.cElems = RecMessageBodySize;
i++;
MessageProps.aPropID = PropIds;
MessageProps.aPropVar = PropVariants;
MessageProps.aStatus = hrProps;
MessageProps.cProp = i;
hResult = MQReceiveMessage(/*(bReadFromPrimary == TRUE) ? */hPrimaryInQueue,// : hSecondaryInQueue,
0,
MQ_ACTION_RECEIVE,
&MessageProps,
NULL,
NULL,
hCursor,
MQ_NO_TRANSACTION);
if (FAILED (hResult) )
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - MQReceiveMessage(hPrimaryInQueue ...) failed (receive)\r\n"
"hResult: %08x",
hResult
);
Status = FALSE;
}
else
{
hResult = StringCbCopyW(RecMessageBody, RecMessageBodySize, LocalRecBody);
Status = TRUE;
}
}
else
{
Status = FALSE;
}
}
else
{
LogEventWithString(
LOGLEVEL_DEBUG,
ERR,
ISAPI_EVENT_DEBUG,
"WorkerFunction() - MQReceiveMessage(hSecondaryInQueue ...) failed\r\n"
"hResult: %08x",
hResult
);
if (hResult != MQ_ERROR_IO_TIMEOUT)
{
LogEvent(LOGLEVEL_ALWAYS, WARN, ISAPI_EVENT_WARNING_PEEK, ISAPI_M_WARNING_PEEK, hResult);
// attemp to re-connect to the queueu
/* if (bReadFromPrimary == TRUE)
{
*/
hResult = MQOpenQueue(g_IsapiParams.InQueueConStr1,
MQ_RECEIVE_ACCESS,
MQ_DENY_NONE,
&hPrimaryInQueue);
if (FAILED(hResult))
{
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"), FAILED_RECONNECT_RECEIVE)!= S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
}
LogEvent(LOGLEVEL_ALWAYS, ERR, ISAPI_EVENT_ERROR_RECONNECT, ISAPI_M_ERROR_RECONNECT, "primary receive queue", hResult);
goto ERRORS;
}
/*
}
else
{
hResult = MQOpenQueue(g_IsapiParams.InQueueConStr1,
MQ_RECEIVE_ACCESS,
MQ_DENY_NONE,
&hPrimaryInQueue);
if (FAILED(hResult))
{
LogEvent(LOGLEVEL_ALWAYS, ERR, ISAPI_EVENT_ERROR_RECONNECT, ISAPI_M_ERROR_RECONNECT, "secondary receive queue", hResult);
goto ERRORS;
}
}
*/
}
else
{
LogEvent(LOGLEVEL_ALWAYS, WARN, ISAPI_EVENT_WARNING_TIMEOUT_EXPIRED, ISAPI_M_WARNING_TIMEOUT_EXPIRED);
}
}
// Close the cursor
if (CursorValid)
MQCloseCursor(hCursor);
} while ((TotalElapsedTime < 20.0) && (!MessageFound));
}
StopRecvQueue = GetTickCount();
StopThread = GetTickCount();
ElapsedTimeSendQueue = StopSendQueue - StartSendQueue;
ElapsedTimeRecvQueue = StopRecvQueue - StartRecvQueue;
ElapsedTimeThread = StopThread - StartThread;
if (g_dwDebugMode & LOGLEVEL_PERF)
{
if (StringCbPrintf(
PerfText,
sizeof(PerfText),
_T("&PerfThread=%ld&PerfSendQueue=%ld&PerfRecvQueue=%ld"),
ElapsedTimeThread,
ElapsedTimeSendQueue,
ElapsedTimeRecvQueue
) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
}
}
// Send the response url to the client
if (!Status)
{
if (StringCbPrintf(ErrorText,sizeof ErrorText,_T("&Code=%d"), MESSAGE_RECEIVE_TIMEOUT)!= S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
}
goto ERRORS;
}
else
{
// Close the Receive queue
if (iType != 1)
{
SendHttpHeaders( pECB, "200 OK", szHeader, FALSE );
}
// convert the wchar message guid to a mbs string
wcstombs(szMessageGuid,wszMessageGuid,wcslen(wszMessageGuid) * sizeof wchar_t);
// Ok we have a message did we get a url ?
if (! _wcsicmp(RecMessageBody, L"NO_SOLUTION"))
{
// This should never happen but just in case send the error url with
// Tracking turned on Log the guid so we can followup later.
LogEvent(LOGLEVEL_ALWAYS, WARN, ISAPI_EVENT_WARNING_NO_SOLUTION, ISAPI_M_WARNING_NO_SOLUTION, szMessageGuid);
if (iType == 1)
{
// send the redirection command
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&State=1%s%s&ID=%s", g_IsapiParams.ErrorUrl,ErrorText,PerfText,szMessageGuid) == S_OK)
{
dwSize = (DWORD)_tcslen(FinalURL);
pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_SEND_URL_REDIRECT_RESP,
FinalURL,
&dwSize,
NULL
);
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
goto ERRORS;
}
}
else
{
// Write the response to the wininet client
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&State=1%s%s&ID=%s", g_IsapiParams.ErrorUrl,ErrorText,PerfText,szMessageGuid) == S_OK)
{
// We want to write the response url to the client
dwSize = (DWORD)strlen( FinalURL );
pECB->WriteClient( pECB->ConnID, FinalURL, &dwSize, 0 );
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
goto ERRORS;
}
}
}
else
{
temp2 = RecMessageBody;
temp2 += (wcslen(RecMessageBody)-1);
while ( (*temp2 != L'=') && (temp2 != RecMessageBody))
-- temp2;
// ok Temp + 1 is our new state value.
if (temp2 != RecMessageBody)
{
iState = _wtoi(temp2+1);
}
// Convert the message body to a TCHAR
wcstombs(szRecMessageBody,RecMessageBody,((wcslen(RecMessageBody)+1) * sizeof wchar_t));
if (iState == 1)
{
wcstombs(szMessageGuid,wszMessageGuid,((wcslen(wszMessageGuid)+1) * sizeof wchar_t));
if (iType == 1) // Watson Client or other web browser
{
// We want to send a redirection command to the client
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&ID=%s%s", szRecMessageBody,szMessageGuid,PerfText) == S_OK)
{
dwSize = (DWORD)_tcslen(FinalURL);
pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_SEND_URL_REDIRECT_RESP,
FinalURL,
&dwSize,
NULL
);
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
goto ERRORS;
}
}
else // WinInet Client
{
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&ID=%s%s", szRecMessageBody,szMessageGuid,PerfText) == S_OK)
{
// We want to write the response url to the client
dwSize = (DWORD)strlen( FinalURL );
pECB->WriteClient( pECB->ConnID, FinalURL, &dwSize, 0 );
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
goto ERRORS;
}
}
}
else // We have a real solution so DO NOT send the Guid
{
if (iType == 1)
{
//wcstombs(szMessageGuid,wszMessageGuid,((wcslen(wszMessageGuid)+1) * sizeof wchar_t));
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s%s", szRecMessageBody,PerfText) == S_OK)
{
dwSize = (DWORD)_tcslen(FinalURL);
pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_SEND_URL_REDIRECT_RESP,
FinalURL,
&dwSize,
NULL
);
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
goto ERRORS;
}
}
else
{
// write the response to the client
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s%s", szRecMessageBody,PerfText) == S_OK)
{
// We want to write the response url to the client
dwSize = (DWORD)strlen( FinalURL );
pECB->WriteClient( pECB->ConnID, FinalURL, &dwSize, 0 );
}
else
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
goto ERRORS;
}
}
}
}
}
if (szTempMessageGuid)
{
RpcStringFreeW(&szTempMessageGuid);
}
pECB->ServerSupportFunction(pECB->ConnID,
HSE_REQ_DONE_WITH_SESSION,
NULL,
NULL,
NULL
);
InterlockedDecrement(&g_dwThreadCount);
if (hPrimaryInQueue)
MQCloseQueue(hPrimaryInQueue);
// if (hSecondaryInQueue)
// MQCloseQueue(hSecondaryInQueue);
if (hPrimaryOutQueue)
MQCloseQueue(hPrimaryOutQueue);
// if (hSecondaryOutQueue)
// MQCloseQueue(hSecondaryOutQueue);
LogEventWithString(LOGLEVEL_TRACE, SUCCESS, ISAPI_EVENT_TRACE, "Exiting WorkerFunction(), no errors!");
_endthreadex(0);
return TRUE;
ERRORS:
if (0 == StartSendQueue)
StopSendQueue = 0;
else if (0 == StopSendQueue)
StopSendQueue = GetTickCount();
if (0 == StartRecvQueue)
StopRecvQueue = 0;
else if (0 == StopRecvQueue)
StopRecvQueue = GetTickCount();
StopThread = GetTickCount();
ElapsedTimeSendQueue = StopSendQueue - StartSendQueue;
ElapsedTimeRecvQueue = StopRecvQueue - StartRecvQueue;
ElapsedTimeThread = StopThread - StartThread;
if (g_dwDebugMode & LOGLEVEL_PERF)
{
if (StringCbPrintf(
PerfText,
sizeof(PerfText),
_T("&PerfThread=%ld&PerfSendQueue=%ld&PerfRecvQueue=%ld"),
ElapsedTimeThread,
ElapsedTimeSendQueue,
ElapsedTimeRecvQueue
) != S_OK)
{
LogEventWithString(
LOGLEVEL_ALWAYS,
ERR,
ISAPI_EVENT_ERROR,
"WorkerFunction() - StringCbPrintf failed"
);
}
}
if (szTempMessageGuid)
{
RpcStringFreeW(&szTempMessageGuid);
}
if (iType == 1)
{
// We want to send a redirection command to the client
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&State=0%s%s", g_IsapiParams.ErrorUrl, ErrorText, PerfText) == S_OK)
{
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "WorkerFunction() - sending redirect\r\nFinalURL: %s", FinalURL);
dwSize = (DWORD)_tcslen(FinalURL);
pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_SEND_URL_REDIRECT_RESP,
FinalURL,
&dwSize,
NULL
);
}
}
else
{
// We want to write the response url to the client
// Write the response to the wininet client
if (StringCbPrintf(FinalURL, sizeof FinalURL, "%s&State=0%s%s", g_IsapiParams.ErrorUrl, ErrorText, PerfText) == S_OK)
{
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "WorkerFunction() - sending response\r\nFinalURL: %s", FinalURL);
// We want to write the response url to the client
SendHttpHeaders( pECB, "200 OK", szHeader, FALSE );
dwSize = (DWORD)strlen( FinalURL );
pECB->WriteClient( pECB->ConnID, FinalURL, &dwSize, 0 );
}
}
pECB->ServerSupportFunction(pECB->ConnID,
HSE_REQ_DONE_WITH_SESSION,
NULL,
NULL,
NULL
);
InterlockedDecrement(&g_dwThreadCount);
if (hPrimaryInQueue)
MQCloseQueue(hPrimaryInQueue);
// if (hSecondaryInQueue)
// MQCloseQueue(hSecondaryInQueue);
if (hPrimaryOutQueue)
MQCloseQueue(hPrimaryOutQueue);
// if (hSecondaryOutQueue)
// MQCloseQueue(hSecondaryOutQueue);
LogEventWithString(LOGLEVEL_TRACE, ERR, ISAPI_EVENT_TRACE, "Exiting WorkerFunction(), error occurred");
_endthreadex(0);
return TRUE;
}
BOOL
SendHttpHeaders(
EXTENSION_CONTROL_BLOCK *pECB,
LPCSTR pszStatus,
LPCSTR pszHeaders,
BOOL fKeepConnection
)
/*++
Purpose:
Send specified HTTP status string and any additional header strings
using new ServerSupportFunction() request HSE_SEND_HEADER_EX_INFO
Arguments:
pECB - pointer to the extension control block
pszStatus - HTTP status string (e.g. "200 OK")
pszHeaders - any additional headers, separated by CRLFs and
terminated by empty line
Returns:
--*/
{
HSE_SEND_HEADER_EX_INFO header_ex_info;
BOOL success;
// test
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "SendHttpHeaders(pECB,\r\npszStatus=%s,\r\npszHeaders=%s,\r\nfKeepConnection=%d)", pszStatus, pszHeaders, (int)fKeepConnection);
header_ex_info.pszStatus = pszStatus;
header_ex_info.pszHeader = pszHeaders;
header_ex_info.cchStatus = (DWORD)strlen( pszStatus );
header_ex_info.cchHeader = (DWORD)strlen( pszHeaders );
header_ex_info.fKeepConn = fKeepConnection;
SetLastError(0);
success = pECB->ServerSupportFunction(
pECB->ConnID,
HSE_REQ_SEND_RESPONSE_HEADER_EX,
&header_ex_info,
NULL,
NULL
);
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "Exiting SendHttpHeaders()\r\nReturn Value: %d\r\nLast Error: %08x", (int)success, GetLastError());
return success;
}
HRESULT
WriteEvent(
LPTSTR lpszSource,
DWORD dwEventType,
DWORD dwEventID,
WORD cStrings,
TCHAR **apwszStrings
)
{
HANDLE hAppLog=NULL;
BOOL bSuccess=FALSE;
WORD wElogType;
DWORD dwErr;
wElogType = (WORD) dwEventType;
if (INVALID_HANDLE_VALUE != g_hEventSource)
{
bSuccess = ReportEvent(
g_hEventSource,
wElogType,
0,
dwEventID,
g_psidUser,
cStrings,
0,
(const TCHAR **) apwszStrings,
NULL
);
dwErr = GetLastError();
LogEventWithString(
LOGLEVEL_TRACE,
INFO,
ISAPI_EVENT_DEBUG,
"WriteEvent() - ReportEvent()\r\n"
"bSuccess: %d\r\n"
"wELogType: %d\r\n"
"dwEventID: %08x\r\n"
"Error: %08lx\r\n"
"Event Source: %s\r\n"
"cStrings: %d\r\n"
"apwszStrings: %08x",
bSuccess,
wElogType,
dwEventID,
GetLastError(),
lpszSource,
cStrings,
(DWORD_PTR)apwszStrings
);
}
else
{
dwErr = GetLastError();
LogEventWithString(
LOGLEVEL_DEBUG,
INFO,
ISAPI_EVENT_DEBUG,
"WriteEvent() - RegisterEventSource() failed\r\n"
"hAppLog: %08x\r\n"
"Last Error: %08lx",
(DWORD_PTR)hAppLog,
dwErr
);
}
return((bSuccess) ? ERROR_SUCCESS : dwErr);
}
void
LogEvent(
IN DWORD dwLevel,
IN ISAPI_EVENT_TYPE emType,
IN DWORD dwEventID,
IN DWORD dwErrorID,
...
)
/*++
Purpose:
Logs a specific event to the event log.
Sample Usage:
LogEvent(LOGLEVEL_ALWAYS, INFO, ISAPI_EVENT_ERROR_SEND, ISAPI_M_ERROR_SEND, szDestination);
Arguments:
emType - event message type (INFO, WRN, ERR, SUCC, AUDITS, AUDITF)
dwEventID - event id from messages.mc
... - variable argument list for any event message parameters
Returns:
--*/
{
DWORD dwResult;
LPTSTR lpszTemp = NULL;
LPTSTR szParams;
LPTSTR* pParams = NULL;
DWORD dwParams = 0;
int i;
va_list arglist;
va_start( arglist, dwErrorID );
if (!(dwLevel & g_dwDebugMode))
{
goto done;
}
LogEventWithString(
LOGLEVEL_TRACE,
INFO,
ISAPI_EVENT_DEBUG,
"LogEvent()\r\n"
"emType: %ld\r\n"
"dwEventID: %08x",
emType,
dwEventID
);
__try {
dwResult = FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_HMODULE |
FORMAT_MESSAGE_FROM_SYSTEM,
g_hModule,
dwErrorID,
LANG_NEUTRAL,
(LPTSTR)&lpszTemp,
0,
&arglist
);
if (dwResult != 0)
{
WriteEvent(_T("OCA_EXTENSION"), emType, dwEventID, 1, &lpszTemp);
if(lpszTemp)
{
LocalFree((HLOCAL)lpszTemp);
}
}
else
{
LogEventWithString(
LOGLEVEL_DEBUG,
INFO,
ISAPI_EVENT_DEBUG,
"LogEvent() - FormatMessage() failed\r\n"
"Last Error: %08x\r\n"
"EventID: %08x",
GetLastError(),
dwEventID
);
}
;
}
__except(EXCEPTION_EXECUTE_HANDLER) {
// this is only for putting a break point here
SetLastError(GetLastError());
}
done:
va_end( arglist );
return;
}
void LogEventWithString(DWORD dwLevel, ISAPI_EVENT_TYPE emType, DWORD dwEventID, LPCTSTR pFormat, ...)
/*++
Purpose:
Logs a generic event with a custom string to the event log. Mostly intended
to be used for debugging purposes.
Sample Usage:
LogEventWithString(LOGLEVEL_ALWAYS, ERR, ISAPI_EVENT_ERROR, "Failed to write %s (%d)", szFilename, dwLastErr);
LogEventWithString(LOGLEVEL_DEBUG, INFO, ISAPI_EVENT_DEBUG, "Failed to write %s (%d)", szFilename, dwLastErr);
Arguments:
emType - event message type (DBG, INFO, WARN, ERROR, SUCCESS, AUDIT_SUCCESS, AUDIT_FAIL)
dwEventID - event id from messages.mc
pFormat - format string to use for variable argument parameter list
... - variable argument list for any event message parameters
Returns:
--*/
{
TCHAR chMsg[256];
LPTSTR lpszStrings[1];
va_list pArg;
if (!(dwLevel & g_dwDebugMode))
{
goto done;
}
va_start(pArg, pFormat);
if (StringCbVPrintf(chMsg,sizeof chMsg, pFormat, pArg) != S_OK)
return;
va_end(pArg);
lpszStrings[0] = chMsg;
if (INVALID_HANDLE_VALUE != g_hEventSource)
{
/* Write to event log. */
ReportEvent(g_hEventSource, emType, 0, dwEventID, g_psidUser, 1, 0, (LPCTSTR*) &lpszStrings[0], NULL);
}
done:
;
}
/*
///////////////////////////////////////////////////////////////////////////////////////
// Routine to Log Fatal Errors to NT Event Log
VOID LogFatalEvent(LPCTSTR pFormat, ...)
{
TCHAR chMsg[256];
LPTSTR lpszStrings[1];
va_list pArg;
va_start(pArg, pFormat);
StringCbVPrintf(chMsg,sizeof chMsg, pFormat, pArg);
va_end(pArg);
lpszStrings[0] = chMsg;
if (INVALID_HANDLE_VALUE != g_hEventSource)
{
//Write to event log.
ReportEvent(g_hEventSource,
EVENTLOG_ERROR_TYPE,
0,
EVENT_ERROR,
NULL,
1,
0,
(LPCTSTR*) &lpszStrings[0],
NULL);
}
}
*/
///////////////////////////////////////////////////////////////////////////////////////
// Routine to setup NT Event logging
DWORD SetupEventLog ( BOOL fSetup )
{
TCHAR s_cszEventLogKey[] = _T("System\\CurrentControlSet\\Services\\EventLog\\Application"); // Event Log
HKEY hKey;
HKEY hSubKey;
TCHAR szEventKey[MAX_PATH];
LONG lRes = 0;
DWORD dwResult = 0;
DWORD dwTypes = EVENTLOG_ERROR_TYPE | EVENTLOG_WARNING_TYPE | EVENTLOG_INFORMATION_TYPE;
dwResult = StringCbCopy(szEventKey, sizeof szEventKey, s_cszEventLogKey);
if (dwResult !=S_OK)
{
LogEvent(LOGLEVEL_ALWAYS, ERR, ISAPI_EVENT_ERROR_SETUP_EVENT_LOG, ISAPI_M_ERROR_SETUP_EVENT_LOG, dwResult);
goto done;
}
else
{
dwResult = StringCbCat(szEventKey, sizeof szEventKey, _T("\\"));
if (dwResult != S_OK)
{
LogEvent(LOGLEVEL_ALWAYS, ERR, ISAPI_EVENT_ERROR_SETUP_EVENT_LOG, ISAPI_M_ERROR_SETUP_EVENT_LOG, dwResult);
goto done;
}
else
{
dwResult = StringCbCat(szEventKey, sizeof szEventKey, _T("OCA_EXTENSION"));
if (dwResult != S_OK)
{
LogEvent(LOGLEVEL_ALWAYS, ERR, ISAPI_EVENT_ERROR_SETUP_EVENT_LOG, ISAPI_M_ERROR_SETUP_EVENT_LOG, dwResult);
goto done;
}
}
}
lRes = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
szEventKey,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&hSubKey,
&dwResult);
if (lRes != ERROR_SUCCESS)
{
goto done;
}
if( TRUE == fSetup )
{
g_hModule = GetModuleHandle(g_cszDefaultExtensionDll);
dwResult = StringCbCopy(g_szAppName,sizeof(g_szAppName), g_cszDefaultExtensionDll);
if (dwResult != S_OK)
{
LogEvent(LOGLEVEL_ALWAYS, ERR, ISAPI_EVENT_ERROR_SETUP_EVENT_LOG, ISAPI_M_ERROR_SETUP_EVENT_LOG, dwResult);
goto done;
}
GetModuleFileName(g_hModule, g_szAppName, sizeof(g_szAppName)/sizeof(g_szAppName[0]) );
RegSetValueEx(hSubKey,_T("EventMessageFile"),0,REG_EXPAND_SZ,(CONST BYTE *)g_szAppName,sizeof(g_szAppName)/sizeof(g_szAppName[0]));
RegSetValueEx(hSubKey,_T("TypesSupported"),0,REG_DWORD, (LPBYTE) &dwTypes, sizeof DWORD);
}
else
{
//RegDeleteKey(HKEY_LOCAL_MACHINE, szEventKey);
}
RegCloseKey(hSubKey);
// Get a handle to use with ReportEvent().
g_hEventSource = RegisterEventSource(NULL, _T("OCA_EXTENSION"));
goto done;
done:
return GetLastError();
}