I needed a simple WildCard Extension to remove a header and could not find one. This needs a little more error checking code but can get the job done. If you use it and add some enhancements or find problems, let me know and I will tune up the example!
#include <windows.h>#include <httpext.h>
// basic pass-through ISAPI extension// based on the C++ sample ISAPI extension at http://msdn.microsoft.com/en-us/library/ms525758(v=vs.90).aspx#Y1930//
BOOL WINAPI GetExtensionVersion( HSE_VERSION_INFO *pVer ){ return TRUE;}
// here we have the ability to clean up any memory we may have allocated.VOID WINAPI ExecuteUrlCompletionCallback( LPEXTENSION_CONTROL_BLOCK pECB, PVOID pUrlInfo, DWORD /* cbIO */, DWORD /* dwError */ ){ HSE_EXEC_UNICODE_URL_INFO *pHseExecUrlInfo = (HSE_EXEC_UNICODE_URL_INFO *)pUrlInfo; HSE_EXEC_URL_STATUS hseExecUrlStatus;
// Set HTTP Status code on ISAPI so that logging works properly // cbIO and dwError should always be 0 if ( !pECB->ServerSupportFunction( pECB->ConnID, HSE_REQ_GET_EXEC_URL_STATUS, &hseExecUrlStatus, NULL, NULL ) ) { OutputDebugString("ExecuteUrlCompletionCallback: Was not able to fetch the HTTP status code.\n"); } else { OutputDebugString("ExecuteUrlCompletionCallback: propagating HTTP status code.\n"); pECB->dwHttpStatusCode = hseExecUrlStatus.uHttpStatusCode; SetLastError( hseExecUrlStatus.dwWin32Error ); }
(void)pECB->ServerSupportFunction ( pECB->ConnID, HSE_REQ_DONE_WITH_SESSION, NULL, NULL, NULL ); if(pHseExecUrlInfo) { if (pHseExecUrlInfo->pszChildHeaders) { OutputDebugString("ExecuteUrlCompletionCallback: status set, freeing pHseExecUrlInfo->pszChildHeaders.\n"); free(pHseExecUrlInfo->pszChildHeaders); }
OutputDebugString("ExecuteUrlCompletionCallback: status set, freeing pHseExecUrlInfo.\n"); free(pHseExecUrlInfo); } else { OutputDebugString("ExecuteUrlCompletionCallback: status set, not freeing pHseExecUrlInfo because it's null.\n"); }}
DWORD WINAPI HttpExtensionProc( EXTENSION_CONTROL_BLOCK *pECB ){ HSE_EXEC_UNICODE_URL_INFO *pHseExecUrlInfo;
pHseExecUrlInfo = (HSE_EXEC_UNICODE_URL_INFO*)malloc(sizeof(HSE_EXEC_UNICODE_URL_INFO));
if(pHseExecUrlInfo) { ZeroMemory(pHseExecUrlInfo, sizeof(HSE_EXEC_UNICODE_URL_INFO) ); // get raw headers and look for transfer encoding chunked: CHAR szBuf[MAX_PATH + 1]; CHAR* pszBuf = szBuf; DWORD dwBuf = MAX_PATH + 1; DWORD dwMaxBufSize = 1024; LPSTR szVariableName = "ALL_RAW";
if ( !pECB->GetServerVariable(pECB->ConnID, szVariableName, pszBuf, &dwBuf) ) { if ( GetLastError() == ERROR_INSUFFICIENT_BUFFER ) { // // Not large enough buffer. Reallocate. // Make sure to not reallocate size blindly (DoS)... // if ( dwBuf > dwMaxBufSize ) { goto Failed; }
pszBuf = new CHAR[dwBuf];
if ( pszBuf != NULL ) { // // Try GetServerVariable again // if ( !pECB->GetServerVariable(pECB->ConnID, szVariableName, pszBuf, &dwBuf) ) { // // Unexpected failure. Fail // goto Failed; }
// // Successfully fetched value into heap buffer // } else { // // Failed to allocate memory. Fail // goto Failed; } } else { // // Deal with GetLastError() however you wish // May optionally decide to fail // // GetLastError() == ERROR_INVALID_INDEX // szVariableName is not a valid server variable name // goto Failed; } }
// // pszBuf points to variable value. Use it. // dwBuf indicates how big the buffer is (NULL included) //
char *pFoundChunked = strstr(pszBuf,"chunked");
if (pFoundChunked!=NULL) { char *pFoundContentLen = strstr(pszBuf,"Content-Length:"); if (pFoundContentLen!=NULL) {
char *pFoundTransferEncoding = strstr(pszBuf,"Transfer-Encoding:"); if (pFoundTransferEncoding != NULL) { // we have both Content-Length and chunked. Because of the issue with wildcard mapped extensions in IIS, we need to eliminate the // chunked header. char *newHeaders = (char *)malloc(sizeof(char)*dwBuf); char *ptr=newHeaders;
//TODO add logic to ensure malloc succeeded!
// if there is a /r/n before this point we will copy all of the stuff before this header, otherwise // this is the first header. char *pFoundEndTransfer = strstr(pFoundTransferEncoding,"\r\n");
if (pFoundEndTransfer != NULL) { // get past the \r\n pFoundEndTransfer++; pFoundEndTransfer++;
if (pszBuf != pFoundTransferEncoding) { //first copy the headers before the chunked. strncpy(ptr,pszBuf,pFoundTransferEncoding-pszBuf); //now move past the end of the encoding ptr+=pFoundTransferEncoding-pszBuf; }
// copy from the end of the transfer header the rest of the headers strcpy(ptr,pFoundEndTransfer); } else { // there is nothing after the encoding header // Copy up until where we found the buffer. strncpy(ptr,pszBuf,pFoundTransferEncoding-pszBuf); ptr+= pFoundTransferEncoding-pszBuf; ptr-=2; //remove terminating "\r\n" //copy a null to terminate the string *ptr='\0';
} // set the new headers on the request! pHseExecUrlInfo->pszChildHeaders = newHeaders; }
}
// // If we've allocated a buffer, cleanup // Failed: if ( pszBuf != NULL && pszBuf != szBuf ) { delete [] pszBuf; }
if(pECB->ServerSupportFunction( pECB->ConnID, HSE_REQ_IO_COMPLETION, ExecuteUrlCompletionCallback, NULL, (LPDWORD)pHseExecUrlInfo )) { if( pECB->ServerSupportFunction( pECB->ConnID, HSE_REQ_EXEC_UNICODE_URL, pHseExecUrlInfo, NULL, NULL ) ) { OutputDebugString("HttpExtensionProc_worker - done returning HSE_STATUS_PENDING\n"); return HSE_STATUS_PENDING; } else { OutputDebugString("HttpExtensionProc_worker - done returning HSE_STATUS_ERROR\n"); return HSE_STATUS_ERROR; } } else { OutputDebugString("HttpExtensionProc_worker - HSE_REQ_IO_COMPLETION failed, returning HSE_STATUS_ERROR\n"); return HSE_STATUS_ERROR; } } else { OutputDebugString("HttpExtensionProc_worker - malloc failed, returning HSE_STATUS_ERROR\n"); return HSE_STATUS_ERROR; }}
BOOL WINAPI TerminateExtension( DWORD dwFlags ){ return TRUE;}
Let me know if this helps you!