とぴやまのブログ(アーカイブ)

元はてなダイアリー

他プロセスのカレントディレクトリを取得する

ようやく手が空いたので作成、といってもコピペでそのまんま。

PEB から RTL_USER_PROCESS_PARAMETERS を取り出す。他プロセス内部の情報なので、ReadProcessMemory() を使う。具体的な手順は、「Navigating the PEB」 に書いてあったのでこれを使用。PEB と RTL_USER_PROCESS_PARAMETERS は、http://www.metawire.org/~akcom/peb.h を拝借した。

あと、PROCESSINFOCLASS や ProcessBasicInformation がひっかかるので、Windows Platform SDK の winternl.h をインクルードする。前もって、_WIN32_WINNT を 0x0500 以上の値を定義しておく必要がある。

#define _WIN32_WINNT 0x0500
#include <windows.h>
#include <winternl.h>

typedef LONG (WINAPI NTQIP)(HANDLE, PROCESSINFOCLASS, PVOID, ULONG, PULONG);

DWORD foo(DWORD dwProcessID, DWORD cchSize, LPWSTR lpWStr)
{
  DWORD     dwSize = 0;
  HANDLE    hProcess;
  BOOL      bSuccess;
  NTQIP     *lpfnNtQueryInformationProcess;
  myPEB     peb;
  RTL_USER_PROCESS_PARAMETERS   Rupp;
  PROCESS_BASIC_INFORMATION     pbi;
  UNICODE_STRING                *pPath;
  
  hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, dwProcessID);
  
  if (NULL != hProcess) {
    pbi.PebBaseAddress = (_PEB *) 0x7ffdf000;
    
    HMODULE hLibrary = GetModuleHandleW(L"ntdll.dll");
    if (NULL != hLibrary) {
      lpfnNtQueryInformationProcess = (NTQIP *) GetProcAddress(hLibrary, "ZwQueryInformationProcess");
      if (NULL != lpfnNtQueryInformationProcess)
        (*lpfnNtQueryInformationProcess)(hProcess, ProcessBasicInformation, &pbi, sizeof(pbi), &dwSize);
    }
    bSuccess = ReadProcessMemory(hProcess, pbi.PebBaseAddress, &peb, sizeof(peb), &dwSize);
    
    if (bSuccess != FALSE) {
      bSuccess = ReadProcessMemory(hProcess, (LPVOID) peb.ProcessParameters, &Rupp, sizeof(RTL_USER_PROCESS_PARAMETERS), &dwSize);
      pPath = &(Rupp.CurrentDirectory.DosPath);
      dwSize = min(pPath->Length, cchSize * sizeof(wchar_t));
    }
    if (bSuccess != FALSE)
      bSuccess = ReadProcessMemory(hProcess, (LPVOID)pPath->Buffer, lpWStr, dwSize, &dwSize);
  }
  
  CloseHandle(hProcess);
  
  return (dwSize / sizeof(wchar_t));
}