title: Why does the TVM_GETITEM message fail on comctl32.ocx or mscomctl.ocx tree views?
body: <p>I wrote a function which can yield the text of a tree view item, even if the tree view is in a remote process. The function allocates two chunks of memory in the remote process, populates a TVITEM structure (which is the copied into the remote process), sends a TVM_GETITEM message and finally reads the contents of the second remote memory chunk back into a local buffer. This is the code:</p>
  
  <pre><code>std::string getTreeViewItemText( HWND treeView, HTREEITEM item )
  {
      DWORD pid;
      ::GetWindowThreadProcessId( treeView, &amp;pid );
  
      HANDLE proc = ::OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, pid );
      if ( !proc )
          // handle error
  
      TVITEM tvi;
      ZeroMemory( &amp;tvi, sizeof(tvi) );
  
      LPVOID tvi_ = ::VirtualAllocEx( proc, NULL, sizeof(tvi), MEM_COMMIT, PAGE_READWRITE);
      if ( !tvi_ )
          // handle error
  
      TCHAR buffer[100] = { 'X' };
  
      LPVOID txt_ = ::VirtualAllocEx( proc, NULL, sizeof(buffer), MEM_COMMIT, PAGE_READWRITE );
      if ( !txt_ )
          // handle error
  
      tvi.mask = TVIF_TEXT | TVIF_HANDLE;
      tvi.pszText =  (LPTSTR)txt_;
      tvi.cchTextMax = sizeof(buffer) / sizeof(buffer[0] );
      tvi.hItem = item;
  
      if ( !::WriteProcessMemory( proc, tvi_, &amp;tvi, sizeof(tvi), NULL ) )
          // handle error
  
      if ( !::SendMessage( treeView, TVM_GETITEM, 0, (LPARAM)tvi_ ) )
          // handle error
  
      if ( !::ReadProcessMemory( proc, (LPCVOID)txt_, buffer, sizeof( buffer ), NULL ) )
          // handle error
  
      ::VirtualFreeEx( proc, tvi_, 0, MEM_RELEASE );
  
      ::VirtualFreeEx( proc, txt_, 0, MEM_RELEASE );
  
      ::CloseHandle( proc );
  
      return buffer;
  }
  </code></pre>
  
  <p>This code works very nicely with the plain tree views which you get when passing the <code>WC_TREEVIEW</code> class name to <code>CreateWindow</code>. However, I noticed that it does not work with the newer trees as provided by MS Common Controls v5 (comctl32.ocx) or MS Common Controls v6 (mscomctl.ocx). In those cases, the returned text is always empty (the buffer is all zeroes). I also noticed that the SendMessage call returns zero (hence the error handling denoted by the <code>// handle error</code> comments above kicks in). It's unclear to me whether this really indicates an error, in any case the buffer is filled with all zeroes.</p>
  
  <p>All other tree view messages (like TVM_GETITEMRECT) seem to work perfectly well.</p>
  
  <p>Does anybody know why that is? I tried playing around with the UNICODE flag (I noticed that <code>TVM_GETITEM</code> is either defined to <code>TVM_GETITEMA</code> or <code>TVM_GETITEMW</code>) but that didn't seem to help.</p>