2010-03-12 245 views
0

我編寫了這個ISAPI篩選器來重寫URL,因爲我們有一些站點移動了位置......基本上,篩選器查看引用鏈接,如果它是本地服務器,它會查看請求的URL並將其與完整的推薦人相比較。如果第一個路徑相同,則不做任何操作,但如果不是,則會從完整的引用鏈接器獲取第一個路徑並將其前置到URL。例如:來自http://myserver/wr/apps/default.htm引用鏈接的/Content/imgs/img.jpg將被重寫爲/wr/Content/imgs/img.jpg。錯誤DLL(ISAPI篩選器)

當我查看日誌文件時,一切看起來都不錯。但是,該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; 
} 
+0

在錯誤發生之前,您在日誌中有多遠? – t0mm13b 2010-03-12 21:35:38

+0

地址0x0002df25是否對應於DLL源中的特定行?順便說一句,0x0002df25是一個非常低的DLL地址加載。最後,你可以附加一個調試器(在崩潰時作爲JIT調試器,或者在崩潰前附加到w3wp.exe)? – 2010-03-12 21:40:45

+0

我確實得到了它的工作......我將tmp2的定義從* tmp2更改爲tmp2 [255]。任何人都可以向我解釋? – Brad 2010-03-12 22:25:39

回答

1

我知道你問一個編程問題,但你可避免整個事情,放棄寫一個ISAPI篩選器的努力,而是使用截止the-擱架通用重寫器,如IIRF

這是一個會做規則你想要什麼:

RewriteCond %{HTTP_REFERER} ^http://localserver/([^/]+)/etc/etc$ 
RewriteCond $1    !*1 
RewriteRule ^/([^/]+)/([^/]+)\.(jpg|gif|png)$ /*1/$1/$2.$3 [L] 
+0

我猜我迷路了,因爲IIS不允許你開箱即用,並且我無法在我們公司的Web服務器上完全安裝某些東西,而無需跳過許多環節並通過軟件評論... – Brad 2010-03-12 22:23:56

+0

我不明白。你正在編寫一個ISAPI過濾器,對吧? IIRF也是一個isapi過濾器。您將以與部署簡單過濾器相同的方式進行部署。無論您對使用IIRF有什麼擔憂,都會與您自己的自定義過濾器相同。沒有?或者你是說,他們會允許你寫一個簡單的過濾器,但不是像IIRF這樣的外部過濾器? – Cheeso 2010-03-12 22:29:35

0

一個潛在的問題是,如果szReferrerszServer是完全相同的值(不知道這是可能的)。但是如果確實發生了,那麼strnstr返回字符串值的長度。換句話說,它返回第一個字符串的長度。在這種情況下,我認爲到tmp的strcpy只會將一個零終止字節放入tmp。以下strchr(tmp+1, ‘/’);然後有未定義的行爲。從它返回的值可能是任何東西(它實際上可能會導致訪問衝突,因爲它可以讀取超出內存的值)。事情可能會在此之後崩潰。

2

如果你真的想編寫和維護一個自定義ISAPI篩選器,我強烈建議兩件事情:使用Visual Studio

  1. 調試。
    如果問題是可重現的,請使用Visual Studio或其他調試器附加到w3wp.exe以捕獲異常。你需要做的是啓動IIS並通過它運行一個請求,以便過濾器被加載。確保DLL的pdb文件與DLL共存。

    然後,您需要啓動Visual Studio,然後附加到調試器中的w3wp.exe進程。然後運行導致錯誤的請求。在Visual Studio裏面,調試器會顯示導致問題的確切線條。

  2. 使用StackWalker

    如果問題不能可靠地重現,那麼當發生問題確實發生時,您需要安排記錄callstack轉儲(包括行號),以便協助診斷它。爲此使用codeplex Stackwalker項目。當異常發生時,您的ISAPI可以將callstack轉儲到日誌文件中,然後您可以在代碼中找到導致故障的行。

相關問題