/*++ 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 #include #include #include #include #include #include #include #include #include #include #include #include // 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
")); // pECB->WriteClient(pECB->ConnID,_T("Starting Scan
"),&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(); }