Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • World
  • Users
  • Groups
Skins
  • Light
  • Cerulean
  • Cosmo
  • Flatly
  • Journal
  • Litera
  • Lumen
  • Lux
  • Materia
  • Minty
  • Morph
  • Pulse
  • Sandstone
  • Simplex
  • Sketchy
  • Spacelab
  • United
  • Yeti
  • Zephyr
  • Dark
  • Cyborg
  • Darkly
  • Quartz
  • Slate
  • Solar
  • Superhero
  • Vapor

  • Default (No Skin)
  • No Skin
Collapse
Code Project
  1. Home
  2. General Programming
  3. C / C++ / MFC
  4. CListCtrl::FindItem crashes

CListCtrl::FindItem crashes

Scheduled Pinned Locked Moved C / C++ / MFC
json
9 Posts 2 Posters 0 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • M Offline
    M Offline
    Maxwell Chen
    wrote on last edited by
    #1

    With FindWindow and FindChildWindows API functions, I got the handle of SysListView32 control of mmsys.cpl panel. When I was trying to search the text of each entries on the ListCtrl, it always crashed. My code snippet is as the below.

    void CMainDlg::OnBnClickedGetDolby()
    {
    // Kill any running window if any.
    KillRunningApplet(_T("Sound"));

    // Launch it.
    if(!LaunchCplApplet(\_T("mmsys.cpl"), 0, 0)) {
    	OutputDebugString(\_T("LaunchCplApplet fails. \\n"));
    	return;
    }
    
    // Make sure the applet pops up.
    CWnd\* pWnd = NULL;
    int i = 0;
    while(!pWnd) {
    	pWnd = FindWindow(NULL, \_T("Sound"));
    	if(pWnd) {
    		OutputDebugString(\_T("Found Sound window. \\n"));
    		break;
    	}
    	Sleep(10);
    	i++;
    	if(i > 1000) {
    		OutputDebugString(\_T("Sound window is not found. \\n"));
    		return;
    	}
    }
    
    // ---
    m\_hListView = NULL;
    for(i = 0; i < 2; i++) {
    	EnumChildWindows(pWnd->m\_hWnd, DoSomethingHelper, (LPARAM)this);
    	if(m\_hListView) {
    		OutputDebugString(\_T("Got SysListView32"));
    		break;
    	}
    	else {
    		OutputDebugString(\_T("SysListView32 is not found."));
    		if(i == 1) {
    			return;
    		}
    	}
    }
    

    // m_pListView->SendMessage(WM_KEYDOWN, VK_DOWN, 0);
    // m_pListView->SendMessage(WM_KEYDOWN, VK_DOWN, 0);

    CListView\* pView = (CListView\*)FromHandle(m\_hListView);
    CListCtrl& Ctrl = pView->GetListCtrl();
    

    // Ctrl.ShowWindow(SW_HIDE); // <-- this line tells me that I got the right handle.

    LVFINDINFO info = {0};
    int iIndex = 0;
    
    info.flags = LVFI\_PARTIAL | LVFI\_STRING;
    info.psz = \_T("Speaker\\0");
    
    if((iIndex = Ctrl.FindItem(&info)) != -1) { // <-- crash at this line.
    	OutputDebugString(\_T("Speaker-like entry is found."));
    }
    

    }

    BOOL CALLBACK DoSomethingHelper(HWND hwnd, LPARAM lParam)
    {
    TCHAR sClassName[MAX_PATH] = {0};
    GetClassName(hwnd, sClassName, MAX_PATH);
    if(wcscmp(sClassName, _T("SysListView32")) == 0) {
    CMainDlg* pMain = (CMainDlg*)lParam;
    pMain->m_hListView = hwnd;
    }
    OutputDebugString(sClassName);
    return TRUE;
    }

    Maxwell Chen

    N 1 Reply Last reply
    0
    • M Maxwell Chen

      With FindWindow and FindChildWindows API functions, I got the handle of SysListView32 control of mmsys.cpl panel. When I was trying to search the text of each entries on the ListCtrl, it always crashed. My code snippet is as the below.

      void CMainDlg::OnBnClickedGetDolby()
      {
      // Kill any running window if any.
      KillRunningApplet(_T("Sound"));

      // Launch it.
      if(!LaunchCplApplet(\_T("mmsys.cpl"), 0, 0)) {
      	OutputDebugString(\_T("LaunchCplApplet fails. \\n"));
      	return;
      }
      
      // Make sure the applet pops up.
      CWnd\* pWnd = NULL;
      int i = 0;
      while(!pWnd) {
      	pWnd = FindWindow(NULL, \_T("Sound"));
      	if(pWnd) {
      		OutputDebugString(\_T("Found Sound window. \\n"));
      		break;
      	}
      	Sleep(10);
      	i++;
      	if(i > 1000) {
      		OutputDebugString(\_T("Sound window is not found. \\n"));
      		return;
      	}
      }
      
      // ---
      m\_hListView = NULL;
      for(i = 0; i < 2; i++) {
      	EnumChildWindows(pWnd->m\_hWnd, DoSomethingHelper, (LPARAM)this);
      	if(m\_hListView) {
      		OutputDebugString(\_T("Got SysListView32"));
      		break;
      	}
      	else {
      		OutputDebugString(\_T("SysListView32 is not found."));
      		if(i == 1) {
      			return;
      		}
      	}
      }
      

      // m_pListView->SendMessage(WM_KEYDOWN, VK_DOWN, 0);
      // m_pListView->SendMessage(WM_KEYDOWN, VK_DOWN, 0);

      CListView\* pView = (CListView\*)FromHandle(m\_hListView);
      CListCtrl& Ctrl = pView->GetListCtrl();
      

      // Ctrl.ShowWindow(SW_HIDE); // <-- this line tells me that I got the right handle.

      LVFINDINFO info = {0};
      int iIndex = 0;
      
      info.flags = LVFI\_PARTIAL | LVFI\_STRING;
      info.psz = \_T("Speaker\\0");
      
      if((iIndex = Ctrl.FindItem(&info)) != -1) { // <-- crash at this line.
      	OutputDebugString(\_T("Speaker-like entry is found."));
      }
      

      }

      BOOL CALLBACK DoSomethingHelper(HWND hwnd, LPARAM lParam)
      {
      TCHAR sClassName[MAX_PATH] = {0};
      GetClassName(hwnd, sClassName, MAX_PATH);
      if(wcscmp(sClassName, _T("SysListView32")) == 0) {
      CMainDlg* pMain = (CMainDlg*)lParam;
      pMain->m_hListView = hwnd;
      }
      OutputDebugString(sClassName);
      return TRUE;
      }

      Maxwell Chen

      N Offline
      N Offline
      Naveen
      wrote on last edited by
      #2

      Which applicaion crashes? the applet or your application?

      nave [OpenedFileFinder] [My Blog]

      M 1 Reply Last reply
      0
      • N Naveen

        Which applicaion crashes? the applet or your application?

        nave [OpenedFileFinder] [My Blog]

        M Offline
        M Offline
        Maxwell Chen
        wrote on last edited by
        #3

        A dialog box popped up saying "Windows Shell Common DLL has stopped working". When I clicked [Close program] of that popup, the applet was gone but my application still was alive. I traced into the source of MFC. The problem is the m_hWnd of that CListCtrl.

        _AFXCMN_INLINE int CListCtrl::FindItem(LVFINDINFO* pFindInfo, int nStart) const
        { ASSERT(::IsWindow(m_hWnd)); return (int) ::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo); }

        Maxwell Chen

        modified on Friday, September 25, 2009 2:09 AM

        N 1 Reply Last reply
        0
        • M Maxwell Chen

          A dialog box popped up saying "Windows Shell Common DLL has stopped working". When I clicked [Close program] of that popup, the applet was gone but my application still was alive. I traced into the source of MFC. The problem is the m_hWnd of that CListCtrl.

          _AFXCMN_INLINE int CListCtrl::FindItem(LVFINDINFO* pFindInfo, int nStart) const
          { ASSERT(::IsWindow(m_hWnd)); return (int) ::SendMessage(m_hWnd, LVM_FINDITEM, nStart, (LPARAM)pFindInfo); }

          Maxwell Chen

          modified on Friday, September 25, 2009 2:09 AM

          N Offline
          N Offline
          Naveen
          wrote on last edited by
          #4

          hmm.. This is because you are passing a string pointer to another process. And when the other process try to access that pointer, exception occurs. You have to allocate the memoy in the target process( VirtualAllocEx() ), copy the string to that process' memory( WriteProcessMemory()). Then set that pointer in the LVM_FINDITEM structure and call FindItem().

          nave [OpenedFileFinder] [My Blog]

          M 1 Reply Last reply
          0
          • N Naveen

            hmm.. This is because you are passing a string pointer to another process. And when the other process try to access that pointer, exception occurs. You have to allocate the memoy in the target process( VirtualAllocEx() ), copy the string to that process' memory( WriteProcessMemory()). Then set that pointer in the LVM_FINDITEM structure and call FindItem().

            nave [OpenedFileFinder] [My Blog]

            M Offline
            M Offline
            Maxwell Chen
            wrote on last edited by
            #5

            I did this as the below, but pBuffer is bad_ptr and WriteProcessMemory returns fail.

            LVFINDINFO info = {0};
            int iIndex = 0;
            TCHAR sTxt\[MAX\_PATH\] = {0};
            SIZE\_T nByte = 0;
            wcscpy(sTxt, \_T("Speaker"));
            
            info.flags = LVFI\_PARTIAL | LVFI\_STRING;
            
            TCHAR\* pBuffer = (TCHAR\*)::VirtualAllocEx(m\_hCplProcess, NULL, MAX\_PATH, MEM\_RESERVE, PAGE\_READWRITE);
            if(!WriteProcessMemory(m\_hCplProcess, pBuffer, sTxt, MAX\_PATH, &nByte)) {
            	return;
            }
            info.psz = pBuffer;
            
            if((iIndex = Ctrl.FindItem(&info)) != -1) {
            	OutputDebugString(\_T("Speaker-like entry is found."));
            }
            
            VirtualFreeEx(m\_hCplProcess, pBuffer, MAX\_PATH, MEM\_RELEASE);
            

            Maxwell Chen

            N 1 Reply Last reply
            0
            • M Maxwell Chen

              I did this as the below, but pBuffer is bad_ptr and WriteProcessMemory returns fail.

              LVFINDINFO info = {0};
              int iIndex = 0;
              TCHAR sTxt\[MAX\_PATH\] = {0};
              SIZE\_T nByte = 0;
              wcscpy(sTxt, \_T("Speaker"));
              
              info.flags = LVFI\_PARTIAL | LVFI\_STRING;
              
              TCHAR\* pBuffer = (TCHAR\*)::VirtualAllocEx(m\_hCplProcess, NULL, MAX\_PATH, MEM\_RESERVE, PAGE\_READWRITE);
              if(!WriteProcessMemory(m\_hCplProcess, pBuffer, sTxt, MAX\_PATH, &nByte)) {
              	return;
              }
              info.psz = pBuffer;
              
              if((iIndex = Ctrl.FindItem(&info)) != -1) {
              	OutputDebugString(\_T("Speaker-like entry is found."));
              }
              
              VirtualFreeEx(m\_hCplProcess, pBuffer, MAX\_PATH, MEM\_RELEASE);
              

              Maxwell Chen

              N Offline
              N Offline
              Naveen
              wrote on last edited by
              #6

              Maxwell Chen wrote:

              TCHAR* pBuffer = (TCHAR*)::VirtualAllocEx(m_hCplProcess, NULL, MAX_PATH, MEM_RESERVE, PAGE_READWRITE);

              You have to pass flAllocationType as MEM_COMMIT|MEM_RESERVE

              nave [OpenedFileFinder] [My Blog]

              M 1 Reply Last reply
              0
              • N Naveen

                Maxwell Chen wrote:

                TCHAR* pBuffer = (TCHAR*)::VirtualAllocEx(m_hCplProcess, NULL, MAX_PATH, MEM_RESERVE, PAGE_READWRITE);

                You have to pass flAllocationType as MEM_COMMIT|MEM_RESERVE

                nave [OpenedFileFinder] [My Blog]

                M Offline
                M Offline
                Maxwell Chen
                wrote on last edited by
                #7

                Naveen wrote:

                You have to pass flAllocationType as MEM_COMMIT|MEM_RESERVE

                I did, too. And it crashed as well ... :sigh:

                TCHAR\* pBuffer = NULL;
                pBuffer = (TCHAR\*)::VirtualAllocEx(m\_hCplProcess, NULL, MAX\_PATH, MEM\_COMMIT | MEM\_RESERVE, PAGE\_READWRITE);
                if(!pBuffer) {
                	return;
                }
                

                I also tried to VirtualAllocEx a LVFINDINFO object to replace the local one. It crashed too but at different line. Not at FindItem call but at the line

                LVFINDINFO* pInfo = NULL;
                // Do VirtualAllocEx for pInfo ...
                pInfo->flags = LVFI_PARTIAL | LVFI_STRING; // <-- crash.

                Maxwell Chen

                N 1 Reply Last reply
                0
                • M Maxwell Chen

                  Naveen wrote:

                  You have to pass flAllocationType as MEM_COMMIT|MEM_RESERVE

                  I did, too. And it crashed as well ... :sigh:

                  TCHAR\* pBuffer = NULL;
                  pBuffer = (TCHAR\*)::VirtualAllocEx(m\_hCplProcess, NULL, MAX\_PATH, MEM\_COMMIT | MEM\_RESERVE, PAGE\_READWRITE);
                  if(!pBuffer) {
                  	return;
                  }
                  

                  I also tried to VirtualAllocEx a LVFINDINFO object to replace the local one. It crashed too but at different line. Not at FindItem call but at the line

                  LVFINDINFO* pInfo = NULL;
                  // Do VirtualAllocEx for pInfo ...
                  pInfo->flags = LVFI_PARTIAL | LVFI_STRING; // <-- crash.

                  Maxwell Chen

                  N Offline
                  N Offline
                  Naveen
                  wrote on last edited by
                  #8

                  Maxwell Chen wrote:

                  I also tried to VirtualAllocEx a LVFINDINFO object to replace the local one. It crashed too but at different line. Not at FindItem call but at the line

                  hmm..I missed that one... here is the correct step.. 1 . VirtualAlloc string in the remote process 2. write the string to that memory. 3. create local object of LVFINDINFO. 4. Set the flags and psz as the memory of the remote process 5. Allocate another memory in the remote process, who's size = sizeof( LVFINDINFO). 6. copy the content of the local LVFINDINFO structure to the remote memory using writeprocessmemory 7. Pass the pointer of the remote LVFINDINFO to the finditem() function

                  nave [OpenedFileFinder] [My Blog]

                  M 1 Reply Last reply
                  0
                  • N Naveen

                    Maxwell Chen wrote:

                    I also tried to VirtualAllocEx a LVFINDINFO object to replace the local one. It crashed too but at different line. Not at FindItem call but at the line

                    hmm..I missed that one... here is the correct step.. 1 . VirtualAlloc string in the remote process 2. write the string to that memory. 3. create local object of LVFINDINFO. 4. Set the flags and psz as the memory of the remote process 5. Allocate another memory in the remote process, who's size = sizeof( LVFINDINFO). 6. copy the content of the local LVFINDINFO structure to the remote memory using writeprocessmemory 7. Pass the pointer of the remote LVFINDINFO to the finditem() function

                    nave [OpenedFileFinder] [My Blog]

                    M Offline
                    M Offline
                    Maxwell Chen
                    wrote on last edited by
                    #9

                    Naveen wrote:

                    3. create local object of LVFINDINFO. 4. Set the flags and psz as the memory of the remote process 5. Allocate another memory in the remote process, who's size = sizeof( LVFINDINFO).

                    Thank you very much. It does not crash now. :-D

                    Maxwell Chen

                    1 Reply Last reply
                    0
                    Reply
                    • Reply as topic
                    Log in to reply
                    • Oldest to Newest
                    • Newest to Oldest
                    • Most Votes


                    • Login

                    • Don't have an account? Register

                    • Login or register to search.
                    • First post
                      Last post
                    0
                    • Categories
                    • Recent
                    • Tags
                    • Popular
                    • World
                    • Users
                    • Groups