c++ - registro - no se pueden guardar cambios a permisos en grace period
Determine la ruta a la clave de registro desde el controlador HKEY en C++ (5)
Estaba emocionado de encontrar este artículo y su solución favorita. Hasta que encontré que el NTDLL.DLL de mi sistema no tenía NtQueryKeyType.
Después de cazar un poco, me encontré con ZwQueryKey en los foros de DDK.
Está en C #, pero aquí está la solución que funciona para mí:
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;
}
Solo lo he intentado mientras se ejecuta como Administrador, lo que puede ser necesario.
El resultado tiene un formato un poco extraño: /REGISTRY/MACHINE/SOFTWARE/company/product
por ejemplo, en lugar de HKEY_LOCAL_MACHINE/SOFTWARE/company/product
.
Dado un identificador a una clave de registro de Windows, como las establecidas por :: RegOpenKeyEx (), ¿es posible determinar la ruta completa a esa clave?
Me doy cuenta de que, en una aplicación simple, todo lo que tienes que hacer es buscar entre 5 o 10 líneas y leer ... pero en una aplicación compleja como la que estoy depurando, la clave que me interesa se puede abrir desde una serie. de llamadas.
Nominalmente no porque es solo un manejador y no hay ninguna API que yo sepa que te permita hacer esto en las API normales de Windows.
SIN EMBARGO, la API nativa tiene muchas funciones, algunas de las cuales le pueden dar mangos abiertos para archivos dados y similares, por lo que quizás haya algo similar para el Registro. Eso y RegMon by SysInternals pueden hacer algo como esto pero tendrás que buscar en Google. Me temo: /
Para ntsd/windbg
:
!handle yourhandle 4
Puede usar RegSaveKey y escribirlo en un archivo, luego mirar el archivo.
Alternativamente, puede mantener un mapa global de HKEYs a LPCWSTRs y agregar entradas cuando los abre y hace búsquedas cada vez.
También puede hacer algo con el comando! Reg en WinDBG / NTSD, pero no puede simplemente darle el HKEY. Tendrás que hacer algunos otros trucos para obtener la información que deseas.
Use la función exportada LoadLibrary
y NtQueryKey
como se NtQueryKey
en el siguiente fragmento de código.
#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;
}
Esto imprimirá la ruta de la clave en la consola:
La ruta clave para 00000FDC es ''/ REGISTRY / MACHINE / SOFTWARE / Microsoft''.