2009-06-01 28 views
18

:: RegOpenKeyEx()によって設定されたものなど、Windowsレジストリキーへのハンドルを指定すると、そのキーへのフルパスを判断できますか?C++のHKEYハンドルからレジストリキーへのパスを決定します。

私は、単純なアプリケーションでは、5行または10行を検索して読み込むだけで済むことを認識していますが、デバッグしているような複雑なアプリケーションでは、興味があるキーを一連の呼び出しから開かれました。

答えて

29

次のコードスニペットのように、エクスポートされた関数LoadLibraryおよびNtQueryKeyを使用してください。

#include <windows.h> 
#include <string> 

typedef LONG NTSTATUS; 

#ifndef STATUS_SUCCESS 
#define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 
#endif 

#ifndef STATUS_BUFFER_TOO_SMALL 
#define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023L) 
#endif 

std::wstring GetKeyPathFromKKEY(HKEY key) 
{ 
    std::wstring keyPath; 
    if (key != NULL) 
    { 
     HMODULE dll = LoadLibrary(L"ntdll.dll"); 
     if (dll != NULL) { 
      typedef DWORD (__stdcall *NtQueryKeyType)(
       HANDLE KeyHandle, 
       int KeyInformationClass, 
       PVOID KeyInformation, 
       ULONG Length, 
       PULONG ResultLength); 

      NtQueryKeyType func = reinterpret_cast<NtQueryKeyType>(::GetProcAddress(dll, "NtQueryKey")); 

      if (func != NULL) { 
       DWORD size = 0; 
       DWORD result = 0; 
       result = func(key, 3, 0, 0, &size); 
       if (result == STATUS_BUFFER_TOO_SMALL) 
       { 
        size = size + 2; 
        wchar_t* buffer = new (std::nothrow) wchar_t[size/sizeof(wchar_t)]; // size is in bytes 
        if (buffer != NULL) 
        { 
         result = func(key, 3, buffer, size, &size); 
         if (result == STATUS_SUCCESS) 
         { 
          buffer[size/sizeof(wchar_t)] = L'\0'; 
          keyPath = std::wstring(buffer + 2); 
         } 

         delete[] buffer; 
        } 
       } 
      } 

      FreeLibrary(dll); 
     } 
    } 
    return keyPath; 
} 

int _tmain(int argc, _TCHAR* argv[]) 
{ 
    HKEY key = NULL; 
    LONG ret = ERROR_SUCCESS; 

    ret = RegOpenKey(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft", &key); 
    if (ret == ERROR_SUCCESS) 
    { 
     wprintf_s(L"Key path for %p is '%s'.", key, GetKeyPathFromKKEY(key).c_str());  
     RegCloseKey(key); 
    } 

    return 0; 
} 

この

は、コンソール上のキーのパスを出力します:00000FDCため

鍵のパスが 'マイクロソフト\ \レジストリ\ MACHINE \ソフトウェア' です。 ntsd/windbgについては

+0

驚くばかり、私はまさにそれを探していた! –

+0

[MSDNのZwQueryKey](http://msdn.microsoft.com/en-us/library/ff567060(v = vs.85).aspx) – Naszta

+0

もう1つ:アプリケーション(ユーザモード)で 'ZwQueryKey'の代わりに' NtQueryKey'を使うべきです。 – Naszta

1

これは単なるハンドルであり、通常のWindows APIでこれを行うために私が知っているAPIはありません。

Native APIにはいくつかの機能がありますが、その中には特定のファイルなどのハンドルを開くことができるものがあります。それとSysInternalsのRegMonはこのようなことをするかもしれませんが、私は恐れています:/

1

RegSaveKeyを使用してファイルに書き込んでからファイルを見てください。

また、HKEYのグローバルマップをLPCWSTRに保存し、それらを開いていつでも参照を追加することができます。

WinDBG/NTSDで!regコマンドを使用して何かを行うこともできますが、単にHKEYにすることはできません。あなたが望む情報を得るには、他のトリッキーなことをする必要があります。

+0

注:この機能にはUAC権限が必要です。 – sergiol

0

私はこの記事とそのうまく言っています解決策を見つけることに興奮しました。 私のシステムのNTDLL.DLLにNtQueryKeyTypeがないことがわかるまでは。

いくつかの狩りをした後、私はDDKフォーラムでZwQueryKeyを実行しました。

これは、C#であるが、ここで私の作品解決策は以下のとおりです。

enum KEY_INFORMATION_CLASS 
{ 
    KeyBasicInformation,   // A KEY_BASIC_INFORMATION structure is supplied. 
    KeyNodeInformation,    // A KEY_NODE_INFORMATION structure is supplied. 
    KeyFullInformation,    // A KEY_FULL_INFORMATION structure is supplied. 
    KeyNameInformation,    // A KEY_NAME_INFORMATION structure is supplied. 
    KeyCachedInformation,   // A KEY_CACHED_INFORMATION structure is supplied. 
    KeyFlagsInformation,   // Reserved for system use. 
    KeyVirtualizationInformation, // A KEY_VIRTUALIZATION_INFORMATION structure is supplied. 
    KeyHandleTagsInformation,  // Reserved for system use. 
    MaxKeyInfoClass     // The maximum value in this enumeration type. 
} 
[StructLayout(LayoutKind.Sequential)] 
public struct KEY_NAME_INFORMATION 
{ 
    public UInt32 NameLength;  // The size, in bytes, of the key name string in the Name array. 
    public char[] Name;   // An array of wide characters that contains the name of the key. 
            // This character string is not null-terminated. 
            // Only the first element in this array is included in the 
            // KEY_NAME_INFORMATION structure definition. 
            // The storage for the remaining elements in the array immediately 
            // follows this element. 
} 

[DllImport("ntdll.dll", SetLastError = true, CharSet = CharSet.Unicode)] 
private static extern int ZwQueryKey(IntPtr hKey, KEY_INFORMATION_CLASS KeyInformationClass, IntPtr lpKeyInformation, int Length, out int ResultLength); 

public static String GetHKeyName(IntPtr hKey) 
{ 
    String result = String.Empty; 
    IntPtr pKNI = IntPtr.Zero; 

    int needed = 0; 
    int status = ZwQueryKey(hKey, KEY_INFORMATION_CLASS.KeyNameInformation, IntPtr.Zero, 0, out needed); 
    if ((UInt32)status == 0xC0000023) // STATUS_BUFFER_TOO_SMALL 
    { 
     pKNI = Marshal.AllocHGlobal(sizeof(UInt32) + needed + 4 /*paranoia*/); 
     status = ZwQueryKey(hKey, KEY_INFORMATION_CLASS.KeyNameInformation, pKNI, needed, out needed); 
     if (status == 0) // STATUS_SUCCESS 
     { 
      char[] bytes = new char[2 + needed + 2]; 
      Marshal.Copy(pKNI, bytes, 0, needed); 
      // startIndex == 2 skips the NameLength field of the structure (2 chars == 4 bytes) 
      // needed/2   reduces value from bytes to chars 
      // needed/2 - 2 reduces length to not include the NameLength 
      result = new String(bytes, 2, (needed/2)-2); 
     } 
    } 
    Marshal.FreeHGlobal(pKNI); 
    return result; 
} 

必要とすることができる管理者として実行している間、私が唯一の今までそれを試してみました。

のように、結果がちょっと変わった形式になっています(HKEY_LOCAL_MACHINE\SOFTWARE\company\productではなく)。

+0

これはNT形式の名前です – paulm

関連する問題