...ing logging 4.0

はてなブログに移行しました。D言語の話とかいろいろ。

他プロセス内のメモリ空間を読み書きする

実装だけじゃなくて他のことも進めなきゃな・・・.

今日は他のアプリケーションが持つツリービューコントロールの各アイテムの矩形領域を得る処理を実装していた.
かなり難航して,丸々一日かかってしまったぞ.
リストビューコントロールでなら情報がいくつかあったけど,ツリービューの方ではあまりなかったので,せっかくだから公開します.
気が向いたらリストビューの方も載せるかも.
でもそっちは探せばそのままのがあります.


// ツリービューのウィンドウハンドル mHwnd から他のプロセスのハンドルを得る
DWORD dwProcessId;
GetWindowThreadProcessId( mHwnd, &dwProcessId);
HANDLE hProcess = OpenProcess( PROCESS_VM_OPERATION | PROCESS_VM_READ | PROCESS_VM_WRITE, FALSE, dwProcessId);
if( !hProcess )
{
return;
}

// 他のプロセスへメモリ空間をコミット
RECT* r = (RECT*)VirtualAllocEx( hProcess, NULL, sizeof(RECT), MEM_RESERVE | MEM_COMMIT, PAGE_READWRITE);
if(r == NULL)
{
return;
}

// rootアイテムの取得
HTREEITEM hItem = TreeView_GetRoot( mHwnd );
if( hItem == NULL )
{
return; // rootアイテムを取得できなかった
}

RECT itemRect;
while( hItem != NULL )
{
itemRect.left = itemRect.top = itemRect.right = itemRect.bottom = 0;

// TVM_GETITEMRECT を使うには SendMessageを呼ぶ前に r に hItem を書き込む必要がある
// さらに r のメモリ空間は他のプロセスなので普通に書き込むことができないから
// 特別な方法で他プロセスのメモリをコピーする
WriteProcessMemory( hProcess, r, &hItem, sizeof(RECT), NULL);
SendMessage( mHwnd, TVM_GETITEMRECT, FALSE, (LPARAM)r);
ReadProcessMemory( hProcess, r, &itemRect, sizeof(RECT), NULL);

//
// ここで itemRect を使う
//

// 次のアイテムを検索
HTREEITEM hNext = TreeView_GetChild( mHwnd, hItem );
if( hNext == NULL )
{
// 子がいないので兄弟を探す
hNext = TreeView_GetNextSibling( mHwnd, hItem );
}
if( hNext == NULL )
{
// 子がおらず兄弟もいないので親を探す
hNext = TreeView_GetParent( mHwnd, hItem );
if( hNext != NULL )
{
// 親はいるが,既に処理しているので親の兄弟を探す
hNext = TreeView_GetNextSibling( mHwnd, hNext/*ここに注意*/ );
if( hNext == NULL )
{
// ツリーのスキャン終了
break;
}
}
else
{
// ツリーのスキャン終了
break;
}
}
hItem = hNext;
}

// 他プロセスのメモリの解放
VirtualFreeEx( hProcess, r, 0, MEM_RELEASE);
CloseHandle( hProcess );