Ошибка DLL (фильтр ISAPI) - PullRequest
       21

Ошибка DLL (фильтр ISAPI)

0 голосов
/ 13 марта 2010

Я написал этот фильтр ISAPI для перезаписи URL, потому что у нас было несколько сайтов, которые переместили местоположения ... По сути, фильтр смотрит на реферер, и если это локальный сервер, он смотрит на запрошенный URL и сравнивает его с полным реферер. Если первый путь идентичен, ничего не делается, но если нет, он берет первый путь от полного реферера и добавляет его к URL. Например: /Content/imgs/img.jpg от реферера http://myserver/wr/apps/default.htm будет переписан как /wr/Content/imgs/img.jpg.

Когда я просматриваю файл журнала, все выглядит хорошо. Однако DLL продолжает сбой со следующей информацией: сбойное приложение w3wp.exe, версия 6.0.3790.3959, сбойный модуль URLRedirector.dll, версия 0.0.0.0, адрес ошибки 0x0002df25.

Вот код:

#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;
}

Ответы [ 3 ]

2 голосов
/ 13 марта 2010

Если вы действительно хотите написать и поддерживать собственный фильтр ISAPI, я настоятельно рекомендую две вещи:

  1. Отладка с использованием Visual Studio
    .
    Если проблема воспроизводима, используйте Visual Studio или другой отладчик для подключения к w3wp.exe, чтобы перехватить исключение. Что вам нужно сделать, это запустить IIS и выполнить запрос через него, чтобы фильтр был загружен. Убедитесь, что файл pdb для DLL находится рядом с DLL.
    .
    Затем вам нужно запустить Visual Studio, а затем подключиться к процессу w3wp.exe в отладчике. Затем выполните запрос, который приводит к ошибке. Внутри Visual Studio отладчик покажет вам точную строку, ведущую к проблеме.

  2. Использование StackWalker
    .
    Если проблема не может быть надежно воспроизведена, вам необходимо организовать запись дампа стека вызовов, включая номера строк, когда проблема действительно , чтобы помочь в ее диагностике. Для этого используйте проект codeplex Stackwalker . Когда возникает исключение, ваш ISAPI может записать стек вызовов в файл журнала, который позволяет вам точно определить строку в вашем коде, ведущую к ошибке.

1 голос
/ 13 марта 2010

Я знаю, что вы задаете вопрос о программировании, но вы могли бы избежать всего этого, отказавшись от усилий по написанию фильтра ISAPI, и вместо этого использовать готовый универсальный преобразователь, например IIRF .

Это правило, которое будет делать то, что вы хотите:

RewriteCond %{HTTP_REFERER} ^http://localserver/([^/]+)/etc/etc$
RewriteCond $1              !*1
RewriteRule ^/([^/]+)/([^/]+)\.(jpg|gif|png)$    /*1/$1/$2.$3    [L]
0 голосов
/ 13 марта 2010

Одна потенциальная проблема заключается в том, что szReferrer и szServer - это одни и те же значения (не уверен, если это возможно). Но если это произойдет, то strnstr возвращает длину строкового значения. Другими словами, он возвращает длину первой строки. В этой ситуации strcpy в tmp, я думаю, помещает только нулевой завершающий байт в tmp. Следующее strchr(tmp+1, ‘/’); имеет неопределенное поведение. Возвращаемое значение может быть любым (на самом деле это может привести к нарушению доступа, потому что он может читать за пределы памяти, что и должен). После этого все может развалиться.

...