I wrote this ISAPI filter to rewrite the URL because we had some sites that moved locations... Basically the filter looks at the referrer, and if it's the local server, it looks at the requested URL and compared it to the full referrer. If the first path is identical, nothing is done, however if not, it takes the first path from the full referrer and prepends it to the URL. For example: /Content/imgs/img.jpg from a referrer of http://myserver/wr/apps/default.htm would be rewritten as /wr/Content/imgs/img.jpg.
When I view the log file, everything looks good. However the DLL keeps faulting with the following information: Faulting application w3wp.exe, version 6.0.3790.3959, faulting module URLRedirector.dll, version 0.0.0.0, fault address 0x0002df25.
Here's the code:
#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <httpfilt.h>
#include <time.h>
#include <string.h>
#ifdef _DEBUG
#define TO_FILE // uncomment out to use a log file
#ifdef TO_FILE
#define DEST ghFile
#define DebugMsg(x) WriteToFile x;
HANDLE ghFile;
#define LOGFILE "W:\\Temp\\URLRedirector.log"
void WriteToFile (HANDLE hFile, char *szFormat, ...) {
char szBuf[1024];
DWORD dwWritten;
va_list list;
va_start (list, szFormat);
vsprintf (szBuf, szFormat, list);
hFile = CreateFile (LOGFILE, GENERIC_WRITE,
0, NULL, OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile != INVALID_HANDLE_VALUE) {
SetFilePointer (hFile, 0, NULL, FILE_END);
WriteFile (hFile, szBuf, lstrlen (szBuf), &dwWritten, NULL);
CloseHandle (hFile);
}
va_end (list);
}
#endif
#endif
BOOL WINAPI __stdcall GetFilterVersion(HTTP_FILTER_VERSION *pVer)
{
/* Specify the types and order of notification */
pVer->dwFlags = (SF_NOTIFY_ORDER_HIGH | SF_NOTIFY_SECURE_PORT | SF_NOTIFY_NONSECURE_PORT
| SF_NOTIFY_PREPROC_HEADERS | SF_NOTIFY_END_OF_NET_SESSION);
pVer->dwFilterVersion = HTTP_FILTER_REVISION;
strcpy(pVer->lpszFilterDesc, "URL Redirector, Version 1.0");
return TRUE;
}
DWORD WINAPI __stdcall HttpFilterProc(HTTP_FILTER_CONTEXT *pfc, DWORD NotificationType, VOID *pvData)
{
CHAR *pPhysPath;
PHTTP_FILTER_URL_MAP pURLMap;
PHTTP_FILTER_PREPROC_HEADERS pHeaderInfo;
CHAR szReferrer[255], szServer[255], szURL[255], szNewURL[255];
DWORD dwRSize = sizeof(szReferrer);
DWORD dwSSize = sizeof(szServer);
DWORD dwUSize = sizeof(szURL);
int iTmp, iTmp2;
CHAR *pos, tmp[255], *tmp2;
switch (NotificationType) {
case SF_NOTIFY_PREPROC_HEADERS :
pHeaderInfo = (PHTTP_FILTER_PREPROC_HEADERS)pvData;
if (pfc->GetServerVariable(pfc, "HTTP_REFERER", szReferrer, &dwRSize))
{
DebugMsg(( DEST,
"Referrer: %s\r\n", szReferrer ));
if (pfc->GetServerVariable(pfc, "SERVER_NAME", szServer, &dwSSize))
DebugMsg(( DEST,
"Server Name: %s\r\n", szServer ));
if (pHeaderInfo->GetHeader(pfc, "URL", szURL, &dwUSize))
DebugMsg(( DEST,
"URL: %s\r\n", szURL ));
iTmp = strnstr(szReferrer, szServer, strlen(szReferrer));
if(iTmp > 0)
{
//Referred is our own server...
strcpy(tmp, szReferrer + iTmp);
DebugMsg(( DEST,
"tmp: %s - %d\r\n", tmp, strlen(tmp) ));
pos = strchr(tmp+1, '/');
DebugMsg(( DEST,
"pos: %s - %d\r\n", pos, strlen(pos) ));
iTmp2 = strlen(tmp) - strlen(pos) + 1;
strncpy(tmp2, tmp, iTmp2);
tmp2[iTmp2] = '\0';
DebugMsg(( DEST,
"tmp2: %s\r\n", tmp2));
if(strncmp(szURL, tmp2, iTmp2) != 0)
{
//First paths don't match, create new URL...
strncpy(szNewURL, tmp2, iTmp2-1);
strcat(szNewURL, szURL);
DebugMsg(( DEST,
"newURL: %s\r\n", szNewURL));
pHeaderInfo->SetHeader(pfc, "URL", szNewURL);
return SF_STATUS_REQ_HANDLED_NOTIFICATION;
}
}
}
break;
default :
break;
}
return SF_STATUS_REQ_NEXT_NOTIFICATION;
}
/* simple function to compare two strings and return the position at which the compare ended */
static int strnstr ( const char *string, const char *strCharSet, int n)
{
int len = (strCharSet != NULL ) ? ((int)strlen(strCharSet )) : 0 ;
int ret, I, J, found;
if ( 0 == n || 0 == len )
{
return -1;
}
ret = -1;
found = 0;
for (I = 0 ; I <= n - len && found != 1 ; I++)
{
J = 0 ;
for ( ; J < len ; J++ )
{
if (toupper(string[I + J]) != toupper(strCharSet [J]))
{
break; // Exit For(J)
}
}
if ( J == len)
{
ret = I + (J);
found = 1;
}
}
return ret;
}