2009-06-01 11 views
18

में HKEY हैंडल से रजिस्ट्री कुंजी के लिए पथ निर्धारित करें Windows रजिस्ट्री कुंजी के लिए हैंडल को देखते हुए, जैसे कि RegopenKeyEx() द्वारा सेट किए गए, क्या यह उस कुंजी के पूर्ण पथ को निर्धारित करना संभव है?सी ++

मुझे एहसास है कि एक साधारण एप्लिकेशन में आपको केवल 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 के लिए कुंजी पथ '\ रजिस्ट्री \ मशीन \ SOFTWARE \ Microsoft' है।

+0

बहुत बढ़िया, मैं बिल्कुल देख रहा था! –

+0

[एमएसडीएन में ZwQueryKey] (http://msdn.microsoft.com/en-us/library/ff567060 (v = vs.85) .aspx)। – Naszta

+0

एक और बात: किसी एप्लिकेशन में (उपयोगकर्ता मोड में) आपको 'ZwQueryKey' के बजाय' NtQueryKey' का उपयोग करना चाहिए। – Naszta

1

नाममात्र नहीं क्योंकि यह सिर्फ एक हैंडल है और कोई एपीआई नहीं है जिसे मैं आपको सामान्य विंडोज एपीआई में करने देता हूं।

कैसे मूल एपीआई में बहुत से फ़ंक्शन हैं जिनमें से कुछ आपको दिए गए फ़ाइलों के लिए खुले हैंडल दे सकते हैं और ऐसा ही रजिस्ट्री के लिए कुछ ऐसा ही हो सकता है। यही कारण है कि और RegMon SysInternals से कुछ इस तरह कर सकते हैं, लेकिन आप गूगल करना होगा मुझे डर लग रहा:/

1

आप RegSaveKey उपयोग करें और यह एक फ़ाइल को लिख सकते हैं, तो फ़ाइल को देखो।

वैकल्पिक रूप से आप HKEYs का वैश्विक मानचित्र LPCWSTRs पर रख सकते हैं और जब आप उन्हें खोलते हैं और जब भी लुकअप करते हैं तो प्रविष्टियां जोड़ सकते हैं।

आप WinDBG/NTSD में reg! आदेश के साथ कुछ भी करने में सक्षम हो सकते हैं, लेकिन आप इसे केवल HKEY नहीं दे सकते। आपको उस जानकारी को प्राप्त करने के लिए आपको कुछ और चाल चलाना होगा।

+0

नोट: उस फ़ंक्शन को यूएसी अधिकारों की आवश्यकता है। – sergiol

0

मैं इस लेख और उसके साथ-साथ पसंद आया समाधान खोजने के लिए उत्साहित थी। जब तक मैंने पाया कि मेरे सिस्टम की NTDLL.DLL में NtQueryKeyType नहीं था।

कुछ शिकार के बाद, मैं डीडीके मंचों में ZwQueryKey भर गया।

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; 
} 

मैं ही कभी यह कोशिश की है, जबकि प्रशासक के रूप में चल रहा है, जो आवश्यक हो सकता है:

यह यहाँ सी # में है, लेकिन समाधान है कि मेरे लिए काम करता है।

परिणाम थोड़ा विचित्र स्वरूपित है: \REGISTRY\MACHINE\SOFTWARE\company\product उदाहरण के लिए, HKEY_LOCAL_MACHINE\SOFTWARE\company\product के बजाय।

+0

यह एनटी प्रारूप नाम है – paulm

 संबंधित मुद्दे

  • कोई संबंधित समस्या नहीं^_^