我用VC写了一个console程序,用来读“设备管理器”中那个systreeview control下的各条Item的文本值,找出我想要的一条。目前是能够在Win2000和WinXP上实现,而Win98上不行。问题出在Win98不支持VirtualAllocEx()这个API。我的代码:
/////////////////////////////////////////////////////////////////////////////////////
   // Allocate memory in the remote process's address space
   TVITEMEX* plvi = (TVITEMEX*) VirtualAllocEx(hProcess, NULL, 4096, MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
   long children = 0;   TVITEMEX item;
   item.hItem = hItem;
   item.mask = TVIF_TEXT | TVIF_CHILDREN;
   item.pszText = (LPTSTR) (plvi + 1);
   item.cchTextMax = buffer_size;   // Write the local LV_ITEM structure to the remote memory block
   WriteProcessMemory(hProcess, plvi, &item, sizeof(item), NULL);   if (!TreeView_GetItem(hWnd, plvi))
   {
        fprintf(stderr, "Error calling SendMessage(TVIF_TEXT)\n");
   }   // Read the remote text string into the end of our clipboard buffer
   ReadProcessMemory(hProcess, plvi + 1, buffer, buffer_size, NULL);
   ReadProcessMemory(hProcess, &plvi->cChildren, &children, sizeof(plvi->cChildren), NULL);        // Free the memory in the remote process's address space
   VirtualFreeEx(hProcess, plvi, 0, MEM_RELEASE);/////////////////////////////////////////////////////////////////////////////////////后来我试了用Win98线性地址的2G-3G共享空间,具体是条用在console中用VirtualAlloc(),将flAllocationType补上|VA_SHARED (注:#define VA_SHARED 0x8000000 这个一个未公开的FLAG,用于指定分配共享内存)。结果在运行到TreeView_GetItem(hWnd, plvi)时,提示RUNDLL32.EXE错误:COMMCTRL.DLL常规保护错误。
经查:TreeView_GetItem(hWnd, plvi)是宏,它其实是调用SendMessage(hWnd, TVM_GETITEM, 0, (LPARAM)(TV_ITEM*)pitem)来实现的。
是不是说sendmessage无法读/写那块共享空间plvi?
后来我也拾了CreateFileMapping+MapViewOfFile方法创建共享内存,结果还是与上面一样。请问:
1。 有没有一种方法可以在Win98实现类似VirtualAllocEx()的功能?
2。 如果用共享内存的方法,上面的问题出在哪?
3。 或者能否给我一种可以实现目的(获得Item的值)的其它方法?请多多指教,谢谢!

解决方案 »

  1.   

    98下就是用CreateFileMapping+MapViewOfFile
      

  2.   

    设备管理器? 用setupapi,没有必要跨进程读取这些数据
      

  3.   

    我要用autoit(脚本工具)操作,所以要找出目标是在第几条位置,不用setupapi。
      

  4.   

    我记得在Windows核心编程里面有介绍98实现VirtualAllocEx的办法。
      

  5.   

    用VA_SHARED flag是正确的做法。我觉得原因可能在于hWnd本身和SendMessage调用方不在同一个进程,导致访问HWND相关结构数据时出现GP。
      

  6.   

    singlerace(独行者):
    谢谢指教。
    有个问题,我在2000和XP中用上述方法没有问题,只不过相应用了VirtualAllocEx函数,但是SendMessage函数还是在console那个进程中调用的啊,而hWnd当然是目标进程(设备管理器)的一个HWND参数了。
    为什么98就不行?我只是吧PLVI这个 TVITEMEX结构放到共享内存中去,在Win98的其它进程中应该期地址也是一样的,这样SendMessage可以读写这个lparam参数了问题出在哪呢?
      

  7.   

    2k/xp的实现和98差的远了去了。Windows本身只有少数几个message支持跨进程传递数据,比如WM_COPYDATA。我的理解是,如果没有特殊说明,需要传递数据的message只能在进程内使用。TVM_GETITEM应该是不支持跨进程的--不支持的意思不是说调用一定失败,而是说不保证成功,具体情况依系统实现而定。
    你这里的错误,我觉得问题不在于读写lparam参数,而在于访问HWND关联的数据结构时出现GP。
    正确的实现应该是code injection。