问题是这样,我做了个钩子程序调用Setwindowlongptr来子类化一个窗口上listview控件,钩子没有任务问题,setwindowlongptr也能调用有返回,但被我hook的那个窗口却出了问题,老是弹出0xXXXXX内存不能read,然后就崩掉了。调试许久找不出原因,后来我尝试了一下用我的dll去子类化别的窗口,结果却正确了,我用spy++,查看了一下两个窗口,发现失败的那个窗口,原先是已经被子类化了的。而成功被我子类化的那个窗口则没有,除此两者没有太大差别。不知是不是因为已经子类化过的窗口就不能再被子类了?因为我的程序去子类化别的窗口的时候可都是成功的。就子类化listview的时候有问题。源码我回去后再贴出来给大家看看,希望可以得到高价指示!

解决方案 »

  1.   

    顶。。
    即使是MFC对象中使用的SubclassWindow 最后调用的也是SetWindowLong
      

  2.   

    另,在子类化后是否使用了
    CallWindowProc
    进行默认处理。。
      

  3.   

    用了,且旧的地址还是通过setwindowlong的返回值得到,但每次都崩
      

  4.   

    终于发现原因了,居然不是我的dll的问题,昏啊。
    LRESULT   CALLBACK   MyWndProc(HWND   hWnd,   UINT   Msg,   WPARAM   wParam,   LPARAM   lParam)  
      {  
               
      SendMessage(HwndOfSeverForm,WM_USER+87,Msg,lParam);   //return DefWindowProc(hWnd,Msg,wParam,lParam);  
      
      return CallWindowProc(OldWndProc,hWnd, Msg, wParam, lParam);  
      
      } 

    LRESULT WINAPI GetMsgProc(int nCode, WPARAM wParam, LPARAM lParam) {   static BOOL bFirstTime = TRUE;   if (bFirstTime) {
          // The DLL just got injected.
          bFirstTime = FALSE;   
     // LRESULT (CALLBACK* )(HWND, UINT, WPARAM, LPARAM)OldWndProc=(LRESULT (CALLBACK* )(HWND, UINT, WPARAM, LPARAM))GetWindowLong(g_HandleOfAlarmLV,GWL_WNDPROC);

            OldWndProc=(WNDPROC)SetWindowLongPtr(g_HandleOfAlarmLV,GWLP_WNDPROC,(LONG_PTR)MyWndProc);
      if(OldWndProc!=NULL)
      MessageBox(NULL, TEXT("DLL已成功改变预警系统窗口消息。"), TEXT("信息"), MB_ICONINFORMATION );
          
    // Uncomment the line below to invoke the debugger 
          // on the process that just got the injected DLL.
          // ForceDebugBreak();      // Create the DIPS Server window to handle the client request.      // Tell the DIPS application that the server is up 
          // and ready to handle requests.
       }   return(CallNextHookEx(g_hHook, nCode, wParam, lParam));
    }
      BOOL WINAPI SetMyHook(DWORD ThreadId,HWND handleOfAlarmLV,HWND handleOfSever)
    {
    BOOL OK=FALSE;
    if(ThreadId!=0)
    {
    //chASSERT(g_hHook==NULL);
    if(g_hHook!=NULL)
    return false; HwndOfSeverForm=handleOfSever;
    g_HandleOfAlarmLV=handleOfAlarmLV;

    g_hHook=SetWindowsHookEx(WH_GETMESSAGE,(HOOKPROC)GetMsgProc,g_HandleOfDll,ThreadId);

    OK=(g_hHook!=NULL);
    if(OK)
    {
               OK=PostThreadMessage(ThreadId,WM_NULL,0,0);
    }
    }
    else
    {
    if(g_hHook==NULL)return false;
    OK=UnhookWindowsHookEx(g_hHook);
    g_hHook=NULL;
    }
    return OK;
    }我在测试该dll的时候用的时候win32控制台项目,用两个EnumChildWindows(NULL,EnumChildProc,NULL)来查找目标窗口的句柄,因为窗口标题是变化的,而类名又是#32770 (对话框),这个样子根本没法用findwindow来找,只能enumchildwindows来一个个搜,但enumchildwindows中再用enumchildwindows,最后才sethook这个样子,还没等开始hook主线程就已经结束了,我当时只好createthread来另开线程,并用waitforsingleobject来等待,这个样子之后就能sethook了,逐步调试来做就很成功,能够子类化目标窗口,但若不设断点直接运行就会出问题,我反复调试觉得好像是线程返回的时候有些东西没处理好,可惜到现在也没发现是什么问题。只知道如若直接把目标窗口的句柄(及线程ID)传给我的钩子函数,一切就能正常。很奇怪!如下为测试项目代码:
    BOOL CALLBACK EnumChildProc2(HWND hwnd, LPARAM lParam )
    {
    if (!hwnd)
    {
    return 0;
    } WCHAR str[14];
    GetClassName(hwnd,str,14); WCHAR str2[14]=TEXT("SysListView32"); int i; for(i=0;i<14;i++)
    {
    if(str[i]!=str2[i])
    break;
    } if(i!=14)
    return true;

    WCHAR str3[6]=TEXT("List2");
    GetWindowText(hwnd,str,6); for(i=0;i<5;i++)
    {
    if(str[i]!=str3[i])
    break;
    } if(i!=5)
    return true; HwndOfLV=hwnd;  
    HINSTANCE Hinst=LoadLibrary(TEXT("HookMsg.dll"));
    SetHook=(BOOL (WINAPI * )(DWORD ,HWND,HWND ))GetProcAddress(Hinst,"SetMyHook");


    BOOL k=SetHook(GetWindowThreadProcessId(hwnd,NULL),hwnd,HwndOfSeverForm);
    return false;
    }BOOL CALLBACK EnumChildProc(HWND hwnd, LPARAM lParam )
    { if (!hwnd)
    {
    return false;
    } WCHAR str[6];;
        
     GetWindowText(hwnd,str, 6);  int i;
      
       
     WCHAR str2[3]=TEXT("预警");
      
    for(i=0;i<2;i++)
    {
    if(str2[i]!=str[i])
    break;
    }
    if(i==2)
    {
    EnumChildWindows(hwnd,EnumChildProc2,NULL);
    return false;
    }
    return true;
    }
     DWORD WINAPI GetWinHwnd (PVOID pvParam)
      {   

      HwndOfSeverForm=FindWindow(TEXT("WindowsForms10.Window.8.app.0.378734a"),TEXT("服务器主端"));   if(HwndOfSeverForm==NULL)
      {
      MessageBox(NULL,TEXT("找不到SEVER!"),TEXT("注意"),MB_ICONINFORMATION);
      return 0;
      }
           
      
      EnumChildWindows(NULL,EnumChildProc,NULL);   return 0;  }
     
    int _tmain(int argc, _TCHAR* argv[])
    {
    //HwndOfSeverForm=FindWindow(TEXT("WindowsForms10.Window.8.app.0.378734a"),TEXT("服务器主端"));
    HANDLE Handle=CreateThread(NULL,0,GetWinHwnd,NULL,0,NULL);
    WaitForSingleObject(Handle,INFINITE);
    //if(HwndOfLV==NULL)
     // {
      //MessageBox(NULL,TEXT("找不到预警窗口!"),TEXT("注意"),MB_ICONINFORMATION);
     // return 0;
      //}

    //BOOL ok=InjectLib(GetWindowThreadProcessId(hwnd,NULL),TEXT("HookMsg.dll"));

    /////////////////
    //
    /// 注意线程的操作即可,dll已无问题!!!!!!!!!!
    ///
    ///////////////////////// while(1)
    {}
    return 0;}