NTSTATUS DrDeleteAllKeys( HANDLE ParentKey ){ NTSTATUS status; status = DrDeleteAllSubKeys(ParentKey); if(!NT_SUCCESS(status)) { return status; } status = ZwDeleteKey(ParentKey); return status; }
NTSTATUS RegistryDeleteSubKey( IN PHANDLE Key, IN PCHAR Name ) { ANSI_STRING Ansi; UNICODE_STRING Unicode; HANDLE SubKey; NTSTATUS status; RtlInitAnsiString(&Ansi, Name); status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE); if (!NT_SUCCESS(status)) goto fail1; status = RegistryOpenKey(Key, &Unicode, KEY_ALL_ACCESS, &SubKey); if (!NT_SUCCESS(status)) goto fail2; status = ZwDeleteKey(SubKey); if (!NT_SUCCESS(status)) goto fail3; ZwClose(SubKey); RtlFreeUnicodeString(&Unicode); return STATUS_SUCCESS; fail3: ZwClose(SubKey); fail2: RtlFreeUnicodeString(&Unicode); fail1: return status; }
void RegDeleteKey(LPWSTR KeyName) { OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING usKeyName; NTSTATUS ntStatus; HANDLE hRegister; RtlInitUnicodeString( &usKeyName, KeyName); InitializeObjectAttributes(&objectAttributes, &usKeyName, OBJ_CASE_INSENSITIVE,//对大小写敏感 NULL, NULL ); ntStatus = ZwOpenKey( &hRegister, KEY_ALL_ACCESS, &objectAttributes); if (NT_SUCCESS(ntStatus)) { ntStatus = ZwDeleteKey(hRegister); ZwClose(hRegister); DbgPrint("ZwDeleteKey success!\n"); } else { DbgPrint("ZwDeleteKey failed!\n"); } }
BOOLEAN RemoveModule(void) { UNICODE_STRING usKeyName, usServiceName; ANSI_STRING asServiceName; BOOLEAN fRet = TRUE; HANDLE hKey; OBJECT_ATTRIBUTES objAttr; NTSTATUS status; IO_STATUS_BLOCK ioStatusBlock; UNICODE_STRING usServicesKey; UNICODE_STRING usEnumKeyName; RtlInitUnicodeString(&usServicesKey, L"\\REGISTRY\\MACHINE\\SYSTEM\\CurrentControlSet\\Services\\"); RtlInitUnicodeString(&usEnumKeyName, L"\\Enum"); RtlInitUnicodeString(&usKeyName, NULL); DBGOUT(("ServiceName ANSI: %s", g_ServiceName)); RtlInitAnsiString(&asServiceName, g_ServiceName); status = RtlAnsiStringToUnicodeString(&usServiceName, &asServiceName, TRUE); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAnsiStringToUnicodeString %08x!", status)); fRet = FALSE; goto end; } DBGOUT(("ServiceName UNICODE: %S", usServiceName.Buffer)); // Remove our registry entries usKeyName.MaximumLength = usServicesKey.Length + usServiceName.Length + usEnumKeyName.Length + sizeof(WCHAR); usKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool, usKeyName.MaximumLength, HELPER_POOL_TAG); RtlZeroMemory(usKeyName.Buffer, usKeyName.MaximumLength); DBGOUT(("KeyName Length: %d", usKeyName.MaximumLength)); RtlCopyUnicodeString(&usKeyName, &usServicesKey); status = RtlAppendUnicodeStringToString(&usKeyName, &usServiceName); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAppendUnicodeStringToString %08x!", status)); fRet = FALSE; goto end; } status = RtlAppendUnicodeStringToString(&usKeyName, &usEnumKeyName); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAppendUnicodeStringToString %08x!", status)); fRet = FALSE; goto end; } InitializeObjectAttributes(&objAttr, &usKeyName,0,NULL,NULL); DBGOUT(("Attempting to delete reg key %S", usKeyName.Buffer)); #ifdef ENABLE_ANTIDETECTION status = s_fnZwOpenKey(&hKey, DELETE, &objAttr); #else status = ZwOpenKey(&hKey, DELETE, &objAttr); #endif if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in ZwOpenKey %08x!", status)); fRet = FALSE; goto end; } status = ZwDeleteKey(hKey); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: Unable to ZwDeleteKey %08x!", status)); fRet = FALSE; goto end; } // Remove our root key entry now RtlZeroMemory(usKeyName.Buffer, usKeyName.MaximumLength); RtlCopyUnicodeString(&usKeyName, &usServicesKey); status = RtlAppendUnicodeStringToString(&usKeyName, &usServiceName); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAppendUnicodeStringToString %08x!", status)); fRet = FALSE; goto end; } InitializeObjectAttributes(&objAttr, &usKeyName,0,NULL,NULL); DBGOUT(("Attempting to delete reg key %S", usKeyName.Buffer)); #ifdef ENABLE_ANTIDETECTION status = s_fnZwOpenKey(&hKey, DELETE, &objAttr); #else status = ZwOpenKey(&hKey, DELETE, &objAttr); #endif if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in ZwOpenKey %08x!", status)); fRet = FALSE; goto end; } status = ZwDeleteKey(hKey); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: Unable to ZwDeleteKey %08x!", status)); fRet = FALSE; goto end; } if(!_wcsnicmp(g_ImagePath.Buffer, L"system32", 8)) { UNICODE_STRING usSysRoot; RtlInitUnicodeString(&usSysRoot, L"\\SystemRoot\\"); // Prepend \SystemRoot\ to the string ExFreePool(usKeyName.Buffer); usKeyName.MaximumLength = usSysRoot.Length + g_ImagePath.Length + sizeof(WCHAR); usKeyName.Buffer = ExAllocatePoolWithTag(NonPagedPool, usKeyName.MaximumLength, HELPER_POOL_TAG); RtlZeroMemory(usKeyName.Buffer, usKeyName.MaximumLength); RtlCopyUnicodeString(&usKeyName, &usSysRoot); status = RtlAppendUnicodeStringToString(&usKeyName, &g_ImagePath); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: FAILURE in RtlAppendUnicodeStringToString %08x!", status)); fRet = FALSE; goto end; } InitializeObjectAttributes(&objAttr, &usKeyName, OBJ_CASE_INSENSITIVE, NULL, NULL); } else { // Use whatever was there InitializeObjectAttributes(&objAttr, &g_ImagePath, OBJ_CASE_INSENSITIVE, NULL, NULL); } // Remove our file DBGOUT(("Removing file %S", objAttr.ObjectName->Buffer)); status = ZwCreateFile(&hKey, DELETE, &objAttr, &ioStatusBlock, (PLARGE_INTEGER)NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_DELETE_ON_CLOSE, 0, 0); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: Unable to ZwCreateFile %08x!", status)); fRet = FALSE; goto end; } status = ZwClose(hKey); if(!NT_SUCCESS(status)) { DBGOUT(("RemoveModule: Unable to ZwClose File %08x!", status)); fRet = FALSE; goto end; } end: RtlFreeUnicodeString(&usServiceName); ExFreePool(usKeyName.Buffer); return fRet; }
void otPlatSettingsWipe(otInstance *otCtx) { NT_ASSERT(otCtx); PMS_FILTER pFilter = otCtxToFilter(otCtx); LogFuncEntry(DRIVER_DEFAULT); // Delete all subkeys of 'OpenThread' if (pFilter->otSettingsRegKey) { NTSTATUS status = STATUS_SUCCESS; ULONG index = 0; UCHAR keyInfo[sizeof(KEY_BASIC_INFORMATION) + 64]; while (status == STATUS_SUCCESS) { ULONG size = sizeof(keyInfo); status = ZwEnumerateKey( pFilter->otSettingsRegKey, index, KeyBasicInformation, keyInfo, size, &size); bool deleted = false; if (NT_SUCCESS(status)) { HANDLE subKey = NULL; OBJECT_ATTRIBUTES attributes; PKEY_BASIC_INFORMATION pKeyInfo = (PKEY_BASIC_INFORMATION)keyInfo; UNICODE_STRING subKeyName = { (USHORT)pKeyInfo->NameLength, (USHORT)pKeyInfo->NameLength, pKeyInfo->Name }; InitializeObjectAttributes( &attributes, &subKeyName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, pFilter->otSettingsRegKey, NULL); // Open the sub key status = ZwOpenKey( &subKey, KEY_ALL_ACCESS, &attributes); if (NT_SUCCESS(status)) { // Delete the key status = ZwDeleteKey(subKey); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "ZwDeleteKey for subkey failed, %!STATUS!", status); } else { deleted = true; } // Close handle ZwClose(subKey); } else { LogError(DRIVER_DEFAULT, "ZwOpenKey for subkey failed, %!STATUS!", status); } } // Only increment index if we didn't delete if (!deleted) { index++; } } } LogFuncExit(DRIVER_DEFAULT); }
NTSTATUS FilterDeleteSetting(_In_ PMS_FILTER pFilter, uint16_t aKey, int aIndex) { HANDLE regKey = NULL; OBJECT_ATTRIBUTES attributes; DECLARE_UNICODE_STRING_SIZE(Name, 20); // Convert 'aKey' to a string RtlIntegerToUnicodeString((ULONG)aKey, 16, &Name); InitializeObjectAttributes( &attributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, pFilter->otSettingsRegKey, NULL); // Open the registry key NTSTATUS status = ZwOpenKey( ®Key, KEY_ALL_ACCESS, &attributes); if (!NT_SUCCESS(status)) { // Key doesn't exist goto error; } // If 'aIndex' is -1 then delete the whole key, otherwise delete the individual value if (aIndex == -1) { // Delete the registry key status = ZwDeleteKey(regKey); } else { UCHAR KeyInfoBuffer[128] = { 0 }; PKEY_FULL_INFORMATION pKeyInfo = (PKEY_FULL_INFORMATION)KeyInfoBuffer; ULONG KeyInfoLength = sizeof(KeyInfoBuffer); // When deleting an individual value, since order doesn't matter, we will actually // copy the last value over the one being deleted and then delete the last value; so // we maintain a contiguous list of numbered values // Query the number of values // Note: Can't use helper function because we already have the key open status = ZwQueryKey( regKey, KeyValueFullInformation, pKeyInfo, KeyInfoLength, &KeyInfoLength); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "ZwQueryKey for %S value failed, %!STATUS!", Name.Buffer, status); goto error; } if ((ULONG)aIndex >= pKeyInfo->Values) { // Attempt to delete beyond the end of the list status = STATUS_OBJECT_NAME_NOT_FOUND; goto error; } else if (pKeyInfo->Values == 1) { // Deleting the only value on the key, go ahead and delete the entire key status = ZwDeleteKey(regKey); } else if (pKeyInfo->Values - 1 != (ULONG)aIndex) { // We aren't deleting the last value so we need to copy the last value // over this one, and then delete the last one. PKEY_VALUE_PARTIAL_INFORMATION pValueInfo = NULL; ULONG ValueInfoLength = 0; // Convert pKeyInfo->Values-1 to a string RtlIntegerToUnicodeString(pKeyInfo->Values - 1, 16, &Name); // Query the key data buffer size status = ZwQueryValueKey( regKey, &Name, KeyValuePartialInformation, pValueInfo, 0, &ValueInfoLength); NT_ASSERT(status != STATUS_SUCCESS); if (status != STATUS_BUFFER_TOO_SMALL) { LogVerbose(DRIVER_DEFAULT, "ZwQueryValueKey for %S value failed, %!STATUS!", Name.Buffer, status); goto error; } pValueInfo = FILTER_ALLOC_MEM(pFilter->FilterHandle, ValueInfoLength); if (pValueInfo == NULL) { status = STATUS_INSUFFICIENT_RESOURCES; goto error; } // Query the data buffer status = ZwQueryValueKey( regKey, &Name, KeyValuePartialInformation, pValueInfo, ValueInfoLength, &ValueInfoLength); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "ZwQueryValueKey for %S value failed, %!STATUS!", Name.Buffer, status); goto cleanup; } // Delete the registry value status = ZwDeleteValueKey( regKey, &Name); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "ZwDeleteValueKey for %S value failed, %!STATUS!", Name.Buffer, status); goto cleanup; } // Convert 'aIndex' to a string RtlIntegerToUnicodeString((ULONG)aIndex, 16, &Name); // Write the data to the registry key we are deleting status = ZwSetValueKey( regKey, &Name, 0, REG_BINARY, (PVOID)pValueInfo->Data, pValueInfo->DataLength); if (!NT_SUCCESS(status)) { LogError(DRIVER_DEFAULT, "ZwSetValueKey for %S value failed, %!STATUS!", Name.Buffer, status); goto cleanup; } cleanup: if (pValueInfo) FILTER_FREE_MEM(pValueInfo); } else { // Deleting the last value in the list (but not the only value) // Just delete the value directly. No need to copy any others. // Convert 'aIndex' to a string RtlIntegerToUnicodeString((ULONG)aIndex, 16, &Name); // Delete the registry value status = ZwDeleteValueKey( regKey, &Name); } } error: if (regKey) ZwClose(regKey); return status; }
VOID DeleteTestKeys( ) /*++ --*/ { NTSTATUS Status; UNICODE_STRING KeyPath; OBJECT_ATTRIBUTES KeyAttributes; HANDLE RootKey = NULL; HANDLE ChildKey = NULL; // // Check if the root key can be opened. If it can be opened, a previous // run must have not completed cleanly. Delete the key and recreate the // root key. // RtlInitUnicodeString(&KeyPath, ROOT_KEY_ABS_PATH); InitializeObjectAttributes(&KeyAttributes, &KeyPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenKey(&RootKey, KEY_ALL_ACCESS, &KeyAttributes); if (Status == STATUS_OBJECT_NAME_NOT_FOUND) { return; } else if (!NT_SUCCESS(Status)) { ErrorPrint("Opening root key fails with unexpected status %x.", Status); } RtlInitUnicodeString(&KeyPath, KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &KeyPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, RootKey, NULL); Status = ZwOpenKey(&ChildKey, KEY_ALL_ACCESS, &KeyAttributes); if (NT_SUCCESS(Status)) { ZwDeleteKey(ChildKey); ZwClose(ChildKey); ChildKey = NULL; } else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) { ErrorPrint("Opening %S key fails with unexpected status %x.", KEY_NAME, Status); } RtlInitUnicodeString(&KeyPath, NOT_MODIFIED_KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &KeyPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, RootKey, NULL); Status = ZwOpenKey(&ChildKey, KEY_ALL_ACCESS, &KeyAttributes); if (NT_SUCCESS(Status)) { ZwDeleteKey(ChildKey); ZwClose(ChildKey); ChildKey = NULL; } else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) { ErrorPrint("Opening %S key fails with unexpected status %x.", NOT_MODIFIED_KEY_NAME, Status); } RtlInitUnicodeString(&KeyPath, MODIFIED_KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &KeyPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, RootKey, NULL); Status = ZwOpenKey(&ChildKey, KEY_ALL_ACCESS, &KeyAttributes); if (NT_SUCCESS(Status)) { ZwDeleteKey(ChildKey); ZwClose(ChildKey); ChildKey = NULL; } else if (Status != STATUS_OBJECT_NAME_NOT_FOUND) { ErrorPrint("Opening %S key fails with unexpected status %x.", MODIFIED_KEY_NAME, Status); } ZwDeleteKey(RootKey); ZwClose(RootKey); return; }
BOOLEAN PreNotificationBypassSample( ) /*++ Routine Description: This sample shows how to bypass a registry operation so that the CM does not process the operation. Unlike block, an operation that is bypassed is still considered successful so the callback must provide the caller with what the CM would have provided. A key and a value are created. However both operations are bypassed by the callback so that the key and value actually created have different names than would is expected. Return Value: TRUE if the sample completed successfully. --*/ { PCALLBACK_CONTEXT CallbackCtx = NULL; NTSTATUS Status; OBJECT_ATTRIBUTES KeyAttributes; UNICODE_STRING Name; HANDLE Key = NULL; DWORD ValueData = 0; BOOLEAN Success = FALSE; InfoPrint(""); InfoPrint("=== Pre-Notification Bypass Sample ===="); // // Create the callback context // CallbackCtx = CreateCallbackContext(CALLBACK_MODE_PRE_NOTIFICATION_BYPASS, CALLBACK_ALTITUDE); if (CallbackCtx == NULL) { goto Exit; } // // Register the callback // Status = CmRegisterCallbackEx(Callback, &CallbackCtx->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtx, &CallbackCtx->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Success = TRUE; // // Create a key and set a value. Both should succeed // RtlInitUnicodeString(&Name, KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, g_RootKey, NULL); Status = ZwCreateKey(&Key, KEY_ALL_ACCESS, &KeyAttributes, 0, NULL, 0, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("ZwCreateKey failed. Status 0x%x", Status); Success = FALSE; } RtlInitUnicodeString(&Name, VALUE_NAME); Status = ZwSetValueKey(g_RootKey, &Name, 0, REG_DWORD, &ValueData, sizeof(ValueData)); if(!NT_SUCCESS(Status)) { ErrorPrint("ZwSetValue failed. Status 0x%x", Status); Success = FALSE; } // // Unregister the callback // Status = CmUnRegisterCallback(CallbackCtx->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); Success = FALSE; } // // Check that a key with the expected name KEY_NAME cannot be found // but a key with the "modified" name can be found. // if (Key != NULL) { ZwClose(Key); } RtlInitUnicodeString(&Name, KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, g_RootKey, NULL); Status = ZwOpenKey(&Key, KEY_ALL_ACCESS, &KeyAttributes); if (Status != STATUS_OBJECT_NAME_NOT_FOUND) { ErrorPrint("ZwOpenKey on key returned unexpected status: 0x%x", Status); if (Key != NULL) { ZwDeleteKey(Key); ZwClose(Key); Key = NULL; } Success = FALSE; } RtlInitUnicodeString(&Name, MODIFIED_KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, g_RootKey, NULL); Status = ZwOpenKey(&Key, KEY_ALL_ACCESS, &KeyAttributes); if (!NT_SUCCESS(Status)) { ErrorPrint("ZwOpenKey on modified key path failed. Status: 0x%x", Status); Success = FALSE; } // // Do the same check by trying to delete a value with VALUE_NAME and // with the "modified" name. // RtlInitUnicodeString(&Name, VALUE_NAME); Status = ZwDeleteValueKey(g_RootKey, &Name); if (Status != STATUS_OBJECT_NAME_NOT_FOUND) { ErrorPrint("ZwDeleteValueKey on original value returned unexpected status: 0x%x", Status); Success = FALSE; } RtlInitUnicodeString(&Name, MODIFIED_VALUE_NAME); Status = ZwDeleteValueKey(g_RootKey, &Name); if (!NT_SUCCESS(Status)) { ErrorPrint("ZwDeleteValueKey on modified value failed. Status: 0x%x", Status); Success = FALSE; } Exit: // // Clean up // if (Key != NULL) { ZwDeleteKey(Key); ZwClose(Key); } if (CallbackCtx != NULL) { ExFreePoolWithTag(CallbackCtx, REGFLTR_CONTEXT_POOL_TAG); } if (Success) { InfoPrint("Pre-Notification Bypass Sample succeeded."); } else { ErrorPrint("Pre-Notification Bypass Sample FAILED."); } return Success; }
static NTSTATUS NTAPI RXactpCommit( PRXACT_CONTEXT Context) { PRXACT_DATA Data; PRXACT_ACTION Action; NTSTATUS Status, TmpStatus; HANDLE KeyHandle; ULONG i; Data = Context->Data; /* The first action record starts after the data header */ Action = (PRXACT_ACTION)(Data + 1); /* Loop all recorded actions */ for (i = 0; i < Data->ActionCount; i++) { /* Translate relative offsets to actual pointers */ Action->KeyName.Buffer = (PWSTR)((PUCHAR)Data + (ULONG_PTR)Action->KeyName.Buffer); Action->ValueName.Buffer = (PWSTR)((PUCHAR)Data + (ULONG_PTR)Action->ValueName.Buffer); Action->ValueData = (PUCHAR)Data + (ULONG_PTR)Action->ValueData; /* Check what kind of action this is */ if (Action->Type == RXactDeleteKey) { /* This is a delete action. Check if we can use a handle */ if ((Action->KeyHandle != INVALID_HANDLE_VALUE) && Context->CanUseHandles) { /* Delete the key by the given handle */ Status = ZwDeleteKey(Action->KeyHandle); if (!NT_SUCCESS(Status)) { return Status; } } else { /* We cannot use a handle, open the key first by it's name */ Status = RXactpOpenTargetKey(Context->RootDirectory, RXactDeleteKey, &Action->KeyName, &KeyHandle); if (NT_SUCCESS(Status)) { Status = ZwDeleteKey(KeyHandle); TmpStatus = NtClose(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); if (!NT_SUCCESS(Status)) { return Status; } } else { /* Failed to open the key, it's ok, if it was not found */ if (Status != STATUS_OBJECT_NAME_NOT_FOUND) return Status; } } } else if (Action->Type == RXactSetValueKey) { /* This is a set action. Check if we can use a handle */ if ((Action->KeyHandle != INVALID_HANDLE_VALUE) && Context->CanUseHandles) { /* Set the key value using the given key handle */ Status = ZwSetValueKey(Action->KeyHandle, &Action->ValueName, 0, Action->ValueType, Action->ValueData, Action->ValueDataSize); if (!NT_SUCCESS(Status)) { return Status; } } else { /* We cannot use a handle, open the key first by it's name */ Status = RXactpOpenTargetKey(Context->RootDirectory, RXactSetValueKey, &Action->KeyName, &KeyHandle); if (!NT_SUCCESS(Status)) { return Status; } /* Set the key value */ Status = ZwSetValueKey(KeyHandle, &Action->ValueName, 0, Action->ValueType, Action->ValueData, Action->ValueDataSize); TmpStatus = NtClose(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); if (!NT_SUCCESS(Status)) { return Status; } } } else { ASSERT(FALSE); return STATUS_INVALID_PARAMETER; } /* Go to the next action record */ Action = (PRXACT_ACTION)((PUCHAR)Action + Action->Size); } return STATUS_SUCCESS; }
NTSTATUS DrDeleteAllSubKeys( HANDLE ParentKey ) { NTSTATUS status; PKEY_BASIC_INFORMATION keyInfo; ULONG outLength; ULONG idxKey; OBJECT_ATTRIBUTES objectAttributes; UNICODE_STRING objectName; HANDLE childKey; keyInfo = (PKEY_BASIC_INFORMATION)ExAllocatePoolWithTag(PagedPool, 512, DEVREG_POOTAG_KEYINFO); if(!keyInfo) { KDPrint(1, ("ExAllocatePoolWithTag(KEY_BASIC_INFORMATION) failed.\n")); return STATUS_INSUFFICIENT_RESOURCES; } status = STATUS_SUCCESS; for(idxKey = 0 ; idxKey < DEVREG_MAX_REGISTRY_KEY; idxKey ++) { status = ZwEnumerateKey( ParentKey, idxKey, KeyBasicInformation, keyInfo, 512, &outLength ); if(status == STATUS_NO_MORE_ENTRIES) { KDPrint(1, ("No more entries.\n")); status = STATUS_SUCCESS; break; } if(status != STATUS_SUCCESS) { ASSERT(status != STATUS_BUFFER_OVERFLOW && status != STATUS_BUFFER_TOO_SMALL); KDPrint(1, ("ZwEnumerateKey() failed. NTSTATUS:%08lx\n", status)); ExFreePool(keyInfo); return STATUS_SUCCESS; } // // Open a sub key // objectName.Length = objectName.MaximumLength = (USHORT)keyInfo->NameLength; objectName.Buffer = keyInfo->Name; InitializeObjectAttributes( &objectAttributes, &objectName, OBJ_KERNEL_HANDLE, ParentKey, NULL ); status = ZwOpenKey(&childKey, KEY_ALL_ACCESS, &objectAttributes); if(!NT_SUCCESS(status)) { KDPrint(1, ("ZwOpenKey() failed. NTSTATUS:%08lx\n", status)); continue; } // // Delete all subkeys // status = DrDeleteAllSubKeys(childKey); if(!NT_SUCCESS(status)) { KDPrint(1, ("Recursive DrDeleteAllSubKeys() failed. NTSTATUS:%08lx\n", status)); ZwClose(childKey); continue; } // // Delete NDAS device instance. // status = ZwDeleteKey(childKey); #if DBG if(!NT_SUCCESS(status)) { KDPrint(1, ("ZwDeleteKey() failed. NTSTATUS:%08lx\n", status)); } #endif ZwClose(childKey); // // One key was deleted, decrement key index. // idxKey--; } ExFreePool(keyInfo); return STATUS_SUCCESS; }
BOOLEAN MultipleAltitudeBlockDuringPreSample( ) /*++ Routine Description: This sample features a stack of three callbacks at different altitudes and demonstrates what happens when middle callback blocks an operation in the pre-notification phase. Return Value: TRUE if the sample completed successfully. --*/ { PCALLBACK_CONTEXT CallbackCtxHigh = NULL; PCALLBACK_CONTEXT CallbackCtxMid = NULL; PCALLBACK_CONTEXT CallbackCtxLow = NULL; NTSTATUS Status; OBJECT_ATTRIBUTES KeyAttributes; UNICODE_STRING Name; HANDLE Key = NULL; BOOLEAN Success = FALSE; InfoPrint(""); InfoPrint("=== Multiple Altitude Block During Pre Sample ===="); // // Create callback contexts for the 3 callbacks. // The high and low callbacks will only monitor how many notifications // they receive. // CallbackCtxHigh = CreateCallbackContext(CALLBACK_MODE_MULTIPLE_ALTITUDE_MONITOR, CALLBACK_HIGH_ALTITUDE); CallbackCtxMid = CreateCallbackContext(CALLBACK_MODE_MULTIPLE_ALTITUDE_BLOCK_DURING_PRE, CALLBACK_ALTITUDE); CallbackCtxLow = CreateCallbackContext(CALLBACK_MODE_MULTIPLE_ALTITUDE_MONITOR, CALLBACK_LOW_ALTITUDE); if ((CallbackCtxHigh == NULL) || (CallbackCtxMid == NULL) || (CallbackCtxLow == NULL)) { goto Exit; } // // Register the callbacks // Status = CmRegisterCallbackEx(Callback, &CallbackCtxHigh->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtxHigh, &CallbackCtxHigh->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Status = CmRegisterCallbackEx(Callback, &CallbackCtxMid->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtxMid, &CallbackCtxMid->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Status = CmRegisterCallbackEx(Callback, &CallbackCtxLow->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtxLow, &CallbackCtxLow->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Success = TRUE; // // Do a create key operation which will be blocked by the middle // callback and fail with STATUS_ACCESS_DENIED // RtlInitUnicodeString(&Name, KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, g_RootKey, NULL); Status = ZwCreateKey(&Key, KEY_ALL_ACCESS, &KeyAttributes, 0, NULL, 0, NULL); if (Status != STATUS_ACCESS_DENIED) { ErrorPrint("ZwCreateKey returned unexpected status 0x%x", Status); Success = FALSE; } // // Unregister the callbacks // Status = CmUnRegisterCallback(CallbackCtxHigh->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); } Status = CmUnRegisterCallback(CallbackCtxMid->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); } Status = CmUnRegisterCallback(CallbackCtxLow->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); } // // Verify that the highest alitude callback receives a pre and a post // notification. It receives a post notification because it returned // STATUS_SUCCESS in the pre-notification so it is guaranteed to get a // post notification. // if ((CallbackCtxHigh->PreNotificationCount != 1) || (CallbackCtxHigh->PostNotificationCount != 1)) { ErrorPrint("High Callback should have seen 1 pre and 1 post notifications."); ErrorPrint("High Callback actually saw %d pre and %d post notifications.", CallbackCtxHigh->PreNotificationCount, CallbackCtxHigh->PostNotificationCount); Success = FALSE; } // // Verify the middle callback receives only a pre notification. // It does not get a post notification because it return a non-success // value in the pre-notification phase. // if ((CallbackCtxMid->PreNotificationCount != 1) || (CallbackCtxMid->PostNotificationCount != 0)) { ErrorPrint("Mid Callback should have seen 1 pre and 0 post notifications."); ErrorPrint("Mid Callback actually saw %d pre and %d post notifications.", CallbackCtxMid->PreNotificationCount, CallbackCtxMid->PostNotificationCount); Success = FALSE; } // // Verify the lowest callback receives no notifications. // Once the middle callback blocks, no callbacks at lower altitudes are // notified. // if ((CallbackCtxLow->PreNotificationCount != 0) || (CallbackCtxLow->PostNotificationCount != 0)) { ErrorPrint("Low Callback should have seen 0 pre and 0 post notifications."); ErrorPrint("Low Callback actually saw %d pre and %d post notifications.", CallbackCtxLow->PreNotificationCount, CallbackCtxLow->PostNotificationCount); Success = FALSE; } Exit: if (Success) { InfoPrint("Multiple Altitude Block During Pre Sample succeeded."); } else { ErrorPrint("Multiple Altitude Block During Pre Sample FAILED."); } // // Clean up // if (Key != NULL) { ZwDeleteKey(Key); ZwClose(Key); } if (CallbackCtxHigh != NULL) { ExFreePoolWithTag(CallbackCtxHigh, REGFLTR_CONTEXT_POOL_TAG); } if (CallbackCtxMid != NULL) { ExFreePoolWithTag(CallbackCtxMid, REGFLTR_CONTEXT_POOL_TAG); } if (CallbackCtxLow != NULL) { ExFreePoolWithTag(CallbackCtxLow, REGFLTR_CONTEXT_POOL_TAG); } return Success; }
BOOLEAN MultipleAltitudeInternalInvocationSample( ) /*++ Routine Description: This sample features a stack of 3 callbacks at different altitudes and demonstrates what happens when the middle callback invokes a registry operation. Return Value: TRUE if the sample completed successfully. --*/ { PCALLBACK_CONTEXT CallbackCtxHigh = NULL; PCALLBACK_CONTEXT CallbackCtxMid = NULL; PCALLBACK_CONTEXT CallbackCtxLow = NULL; NTSTATUS Status; OBJECT_ATTRIBUTES KeyAttributes; UNICODE_STRING Name; HANDLE Key = NULL; BOOLEAN Success = FALSE; InfoPrint(""); InfoPrint("=== Multiple Altitude Internal Invocation Sample ===="); // // Create callback contexts for the 3 callbacks. // The high and low callbacks will only monitor how many notifications // they receive. // CallbackCtxHigh = CreateCallbackContext(CALLBACK_MODE_MULTIPLE_ALTITUDE_MONITOR, CALLBACK_HIGH_ALTITUDE); CallbackCtxMid = CreateCallbackContext(CALLBACK_MODE_MULTIPLE_ALTITUDE_INTERNAL_INVOCATION, CALLBACK_ALTITUDE); CallbackCtxLow = CreateCallbackContext(CALLBACK_MODE_MULTIPLE_ALTITUDE_MONITOR, CALLBACK_LOW_ALTITUDE); if ((CallbackCtxHigh == NULL) || (CallbackCtxMid == NULL) || (CallbackCtxLow == NULL)) { goto Exit; } // // Register the callbacks // Status = CmRegisterCallbackEx(Callback, &CallbackCtxHigh->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtxHigh, &CallbackCtxHigh->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Status = CmRegisterCallbackEx(Callback, &CallbackCtxMid->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtxMid, &CallbackCtxMid->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Status = CmRegisterCallbackEx(Callback, &CallbackCtxLow->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtxLow, &CallbackCtxLow->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Success = TRUE; // // Create a key. When the middle callback receives the pre-notification // and the post-notification for this create it will perform an open key // and a close key operation. // RtlInitUnicodeString(&Name, KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, g_RootKey, NULL); Status = ZwCreateKey(&Key, KEY_ALL_ACCESS, &KeyAttributes, 0, NULL, 0, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("ZwCreateKey returned unexpected status 0x%x", Status); Success = FALSE; } // // Unregister the callbacks // Status = CmUnRegisterCallback(CallbackCtxHigh->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); Success = FALSE; } Status = CmUnRegisterCallback(CallbackCtxMid->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); Success = FALSE; } Status = CmUnRegisterCallback(CallbackCtxLow->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); Success = FALSE; } // // Verify the highest altitude callback receives one pre and one post // notification. This callback does not get notifications for the // registry operations called by the middle callback. // if ((CallbackCtxHigh->PreNotificationCount != 1) || (CallbackCtxHigh->PostNotificationCount != 1)) { ErrorPrint("High Callback should have seen 1 pre and 1 post notifications."); ErrorPrint("High Callback actually saw %d pre and %d post notifications.", CallbackCtxHigh->PreNotificationCount, CallbackCtxHigh->PostNotificationCount); Success = FALSE; } // // Verify the middle callback receives one pre and one post notification. // This callback does not get notifications for the registry operations // that it calls. // if ((CallbackCtxMid->PreNotificationCount != 1) || (CallbackCtxMid->PostNotificationCount != 1)) { ErrorPrint("Mid Callback should have seen 1 pre and 1 post notifications."); ErrorPrint("Mid Callback actually saw %d pre and %d post notifications.", CallbackCtxMid->PreNotificationCount, CallbackCtxMid->PostNotificationCount); Success = FALSE; } // // Verify the lowest callback receives 5 pre-notifications and 5 // post-notifications. This callback receives 1 pre and 1 post from the // original create key operation. It also receives 2 pre and 2 post for // the open key and close key operations called by the middle callback // during the pre phase of the create key and then 2 pre and 2 post again // for the calls in the post phase of the create key. // if ((CallbackCtxLow->PreNotificationCount != 5) || (CallbackCtxLow->PostNotificationCount != 5)) { ErrorPrint("Low Callback should have seen 5 pre and 5 post notifications."); ErrorPrint("Low Callback actually saw %d pre and %d post notifications.", CallbackCtxLow->PreNotificationCount, CallbackCtxLow->PostNotificationCount); Success = FALSE; } Exit: if (Success) { InfoPrint("Multiple Altitude Internal Invocation Sample succeeded."); } else { ErrorPrint("Multiple Altitude Internal Invocation Sample FAILED."); } // // Clean up // if (Key != NULL) { ZwDeleteKey(Key); ZwClose(Key); } if (CallbackCtxHigh != NULL) { ExFreePoolWithTag(CallbackCtxHigh, REGFLTR_CONTEXT_POOL_TAG); } if (CallbackCtxMid != NULL) { ExFreePoolWithTag(CallbackCtxMid, REGFLTR_CONTEXT_POOL_TAG); } if (CallbackCtxLow != NULL) { ExFreePoolWithTag(CallbackCtxLow, REGFLTR_CONTEXT_POOL_TAG); } return Success; }
VOID SoundCleanup( IN PGLOBAL_DEVICE_INFO pGDI ) /*++ Routine Description: Clean up all resources allocated by our initialization Arguments: pGDI - Pointer to global data Return Value: NONE --*/ { PGLOBAL_DEVICE_INFO NextGDI; PGLOBAL_DEVICE_INFO FirstGDI; PDRIVER_OBJECT DriverObject; FirstGDI = pGDI; for (;;) { NextGDI = pGDI->Next; // // Free the synth device // SynthCleanup(&pGDI->Synth); // // Reset MPU401 if any // if (pGDI->Hw.MPU401.PortBase != NULL) { // // Just in case // READ_PORT_UCHAR(pGDI->Hw.MPU401.PortBase + MPU401_REG_DATA); MPU401Write(pGDI->Hw.MPU401.PortBase, TRUE, MPU401_CMD_RESET); } // // Free our interrupt // if (pGDI->WaveInfo.Interrupt) { IoDisconnectInterrupt(pGDI->WaveInfo.Interrupt); } // // Free our DMA Buffer // SoundFreeCommonBuffer(&pGDI->WaveInfo.DMABuf); // // Unregister shutdown notification // if (pGDI->ShutdownRegistered) { IoUnregisterShutdownNotification(pGDI->DeviceObject[WaveInDevice]); } // // Free our I/O Ports // if (pGDI->MemType == 0) { if (pGDI->Hw.PortBase != NULL) { MmUnmapIoSpace(pGDI->Hw.PortBase, NUMBER_OF_SOUND_PORTS); } if (pGDI->Hw.MPU401.PortBase != NULL) { MmUnmapIoSpace(pGDI->Hw.MPU401.PortBase, NUMBER_OF_MPU401_PORTS); } #ifdef SB_CD if (pGDI->Hw.SBCDBase != NULL) { MmUnmapIoSpace(pGDI->Hw.SBCDBase, 6); } #endif // SB_CD } // // Free device name // if (pGDI->RegistryPathName) { HANDLE hKey; // // Free devices key // if (NT_SUCCESS(SoundOpenDevicesKey(pGDI->RegistryPathName, &hKey))) { ZwDeleteKey(hKey); ZwClose(hKey); } ExFreePool(pGDI->RegistryPathName); } // // Save driver object // DriverObject = pGDI->DriverObject; // // Free the Pool // ExFreePool(pGDI); if (NextGDI == FirstGDI) { break; } else { pGDI = NextGDI; } } // // Free all devices for this driver. This will free everything for // every card. // if (DriverObject != NULL) { while (DriverObject->DeviceObject != NULL) { /* ** Undeclare resources used by device and ** delete the device object and associated data */ SoundFreeDevice(DriverObject->DeviceObject); } } }
//-.-.-.-.-.-.-.-.-.-.-.-.-.-.- DriverParametersSubKeyDelete -.-.-.-.-.-.-.-.-.-.-.-.-.-.- // NTSTATUS DriverParametersSubKeyDelete( WDFDRIVER Driver, DtString* pKeyName) { NTSTATUS NtStatus = STATUS_SUCCESS; DtStringChar* pRegistryPath; DtString RegistryPath; DtString FullKeyName; UInt PathLength; HANDLE hKey; OBJECT_ATTRIBUTES ObjectAttributes; KEY_BASIC_INFORMATION* pKeyInfo; ULONG Size; ULONG ResultSize; Int Index; DT_STRING_DECL(ParamItemName, "\\Parameters\\"); DT_ASSERT(KeGetCurrentIrql()<=PASSIVE_LEVEL); // Build the full path pRegistryPath = WdfDriverGetRegistryPath(Driver); PathLength = wcslen(pRegistryPath); DT_STRING_INIT_CONST(RegistryPath, pRegistryPath, PathLength); // Allocate struct for key information result Size = sizeof(KEY_BASIC_INFORMATION)+100; pKeyInfo = DtMemAllocPool(DtPoolNonPaged, Size, SAL_TAG); if (pKeyInfo == NULL) return STATUS_NO_MEMORY; // Allocate a new DtString buffer for the complete path inclusive a '\0' character // and extra '\\' if (!DT_SUCCESS(DtStringAlloc(&FullKeyName, PathLength+ DtStringGetStringLength(&ParamItemName)+ DtStringGetStringLength(pKeyName)+ 100+1+1))) { DtMemFreePool(pKeyInfo, SAL_TAG); return STATUS_NO_MEMORY; } DtStringAppendDtString(&FullKeyName, &RegistryPath); DtStringAppendDtString(&FullKeyName, &ParamItemName); DtStringAppendDtString(&FullKeyName, pKeyName); // Initialize key to open InitializeObjectAttributes(&ObjectAttributes, &FullKeyName, OBJ_KERNEL_HANDLE, NULL, NULL); NtStatus = ZwOpenKey(&hKey, KEY_ENUMERATE_SUB_KEYS , &ObjectAttributes); if (NT_SUCCESS(NtStatus)) { Index = 0; NtStatus = STATUS_SUCCESS; // Enumerate all keys while (NtStatus != STATUS_NO_MORE_ENTRIES) { NtStatus = ZwEnumerateKey(hKey, Index, KeyBasicInformation, pKeyInfo, Size, &ResultSize); if (NT_SUCCESS(NtStatus)) { DtString SubKey; // Build key to delete pKeyInfo->Name[pKeyInfo->NameLength/2] = L'\0'; DT_STRING_INIT_CONST(SubKey, pKeyInfo->Name, ((USHORT)pKeyInfo->NameLength/2)); DtStringClear(&FullKeyName); DtStringAppendDtString(&FullKeyName, pKeyName); DtStringAppendChars(&FullKeyName, "\\"); DtStringAppendDtString(&FullKeyName, &SubKey); DtDbgOut(MAX, SAL, "Delete SubKey %S.", FullKeyName.Buffer); NtStatus = DriverParametersKeyDelete(Driver, &FullKeyName); if (!NT_SUCCESS(NtStatus)) DtDbgOut(ERR, SAL, "Error deleting SubKey %S. Error: %x", FullKeyName.Buffer, NtStatus); } // In case deletion failed, skip this entry if (!NT_SUCCESS(NtStatus)) Index++; } NtStatus = ZwDeleteKey(hKey); ZwClose(hKey); } DtMemFreePool(pKeyInfo, SAL_TAG); DtStringFree(&FullKeyName); return NtStatus; }
BOOLEAN SetCallContextSample( ) /*++ Routine Description: This sample shows how a registry callback can associate a context with a registry operation during the pre-notification phase so that it is available in the post-notification phase. Return Value: TRUE if the sample completed successfully. --*/ { PCALLBACK_CONTEXT CallbackCtx = NULL; NTSTATUS Status; OBJECT_ATTRIBUTES KeyAttributes; UNICODE_STRING Name; HANDLE Key = NULL; DWORD ValueData = 0; BOOLEAN Success = FALSE; InfoPrint(""); InfoPrint("=== Set Operation Context Sample ===="); // // Create the callback context // CallbackCtx = CreateCallbackContext(CALLBACK_MODE_SET_CALL_CONTEXT, CALLBACK_ALTITUDE); if (CallbackCtx == NULL) { goto Exit; } // // Register callback with the context // Status = CmRegisterCallbackEx(Callback, &CallbackCtx->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtx, &CallbackCtx->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Success = TRUE; // // Create a key and set a value. // RtlInitUnicodeString(&Name, KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, g_RootKey, NULL); Status = ZwCreateKey(&Key, KEY_ALL_ACCESS, &KeyAttributes, 0, NULL, 0, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("ZwCreateKey failed. Status 0x%x", Status); Success = FALSE; } RtlInitUnicodeString(&Name, VALUE_NAME); Status = ZwSetValueKey(g_RootKey, &Name, 0, REG_DWORD, &ValueData, sizeof(ValueData)); if(!NT_SUCCESS(Status)) { ErrorPrint("ZwSetValue failed. Status 0x%x", Status); Success = FALSE; } // // Unregister the callback // Status = CmUnRegisterCallback(CallbackCtx->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); Success = FALSE; } // // Check that the callback records 2 in OperationContextCount. // The count should be incremented once in the post-notification for the // create key and once for the set value. // if (CallbackCtx->NotificationWithContextCount != 2) { ErrorPrint("Callback OperationWithContextCount expected 2, got %d", CallbackCtx->NotificationWithContextCount); Success = FALSE; } Exit: if (Success == TRUE) { InfoPrint("Set Call Context sample succeeded."); } else { ErrorPrint("Set Call Context sample FAILED."); } // // Clean up // if (Key != NULL) { ZwDeleteKey(Key); ZwClose(Key); } RtlInitUnicodeString(&Name, VALUE_NAME); ZwDeleteValueKey(g_RootKey, &Name); if (CallbackCtx != NULL) { ExFreePoolWithTag(CallbackCtx, REGFLTR_CONTEXT_POOL_TAG); } return Success; }
NTSTATUS DeleteKey(HANDLE hKey) { return ZwDeleteKey(hKey); }
NTSTATUS DoCallbackSamples( _In_ PDEVICE_OBJECT DeviceObject, _In_ PIRP Irp ) /*++ Routine Description: This routine creates the root test key and then invokes the sample. It records the results of each sample in an array that it returns to the usermode program. Arguments: DeviceObject - The device object receiving the request. Irp - The request packet. Return Value: NTSTATUS --*/ { NTSTATUS Status; PIO_STACK_LOCATION IrpStack; ULONG OutputBufferLength; PDO_KERNELMODE_SAMPLES_OUTPUT Output; UNICODE_STRING KeyPath; OBJECT_ATTRIBUTES KeyAttributes; UNREFERENCED_PARAMETER(DeviceObject); // // Get the output buffer from the irp and check it is as large as expected. // IrpStack = IoGetCurrentIrpStackLocation(Irp); OutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength; if (OutputBufferLength < sizeof (DO_KERNELMODE_SAMPLES_OUTPUT)) { Status = STATUS_INVALID_PARAMETER; goto Exit; } Output = (PDO_KERNELMODE_SAMPLES_OUTPUT) Irp->AssociatedIrp.SystemBuffer; // // Clean up test keys in case the sample terminated uncleanly. // DeleteTestKeys(); // // Create the root key and the modified root key // RtlInitUnicodeString(&KeyPath, ROOT_KEY_ABS_PATH); InitializeObjectAttributes(&KeyAttributes, &KeyPath, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwCreateKey(&g_RootKey, KEY_ALL_ACCESS, &KeyAttributes, 0, NULL, 0, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("ZwCreateKey failed. Status 0x%x", Status); return Status; } // // Call each demo and record the results in the Output->SampleResults // array // Output->SampleResults[KERNELMODE_SAMPLE_PRE_NOTIFICATION_BLOCK] = PreNotificationBlockSample(); Output->SampleResults[KERNELMODE_SAMPLE_PRE_NOTIFICATION_BYPASS] = PreNotificationBypassSample(); Output->SampleResults[KERNELMODE_SAMPLE_POST_NOTIFICATION_OVERRIDE_SUCCESS] = PostNotificationOverrideSuccessSample(); Output->SampleResults[KERNELMODE_SAMPLE_POST_NOTIFICATION_OVERRIDE_ERROR] = PostNotificationOverrideErrorSample(); Output->SampleResults[KERNELMODE_SAMPLE_TRANSACTION_ENLIST] = TransactionEnlistSample(); Output->SampleResults[KERNELMODE_SAMPLE_TRANSACTION_REPLAY] = TransactionReplaySample(); Output->SampleResults[KERNELMODE_SAMPLE_SET_CALL_CONTEXT] = SetObjectContextSample(); Output->SampleResults[KERNELMODE_SAMPLE_SET_OBJECT_CONTEXT] = SetCallContextSample(); Output->SampleResults[KERNELMODE_SAMPLE_MULTIPLE_ALTITUDE_BLOCK_DURING_PRE] = MultipleAltitudeBlockDuringPreSample(); Output->SampleResults[KERNELMODE_SAMPLE_MULTIPLE_ALTITUDE_INTERNAL_INVOCATION] = MultipleAltitudeInternalInvocationSample(); Output->SampleResults[KERNELMODE_SAMPLE_VERSION_CREATE_OPEN_V1] = CreateOpenV1Sample(); Irp->IoStatus.Information = sizeof(DO_KERNELMODE_SAMPLES_OUTPUT); Exit: if (g_RootKey) { ZwDeleteKey(g_RootKey); ZwClose(g_RootKey); } InfoPrint(""); InfoPrint("Kernel Mode Samples End"); InfoPrint(""); return Status; }
NTSTATUS NTAPI RtlInitializeRXact( HANDLE RootDirectory, BOOLEAN Commit, PRXACT_CONTEXT *OutContext) { NTSTATUS Status, TmpStatus; PRXACT_CONTEXT Context; PKEY_VALUE_FULL_INFORMATION KeyValueInformation; KEY_VALUE_BASIC_INFORMATION KeyValueBasicInfo; UNICODE_STRING ValueName; UNICODE_STRING KeyName; OBJECT_ATTRIBUTES ObjectAttributes; RXACT_INFO TransactionInfo; ULONG Disposition; ULONG ValueType; ULONG ValueDataLength; ULONG Length; HANDLE KeyHandle; /* Open or create the 'RXACT' key in the root directory */ RtlInitUnicodeString(&KeyName, L"RXACT"); InitializeObjectAttributes(&ObjectAttributes, &KeyName, OBJ_CASE_INSENSITIVE | OBJ_OPENIF, RootDirectory, NULL); Status = ZwCreateKey(&KeyHandle, KEY_READ | KEY_WRITE | DELETE, &ObjectAttributes, 0, NULL, 0, &Disposition); if (!NT_SUCCESS(Status)) { return Status; } /* Allocate a new context */ Context = RtlAllocateHeap(RtlGetProcessHeap(), 0, sizeof(*Context)); *OutContext = Context; if (Context == NULL) { TmpStatus = ZwDeleteKey(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); TmpStatus = NtClose(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); return STATUS_NO_MEMORY; } /* Initialize the context */ RXactInitializeContext(Context, RootDirectory, KeyHandle); /* Check if we created a new key */ if (Disposition == REG_CREATED_NEW_KEY) { /* The key is new, set the default value */ TransactionInfo.Revision = 1; RtlInitUnicodeString(&ValueName, NULL); Status = ZwSetValueKey(KeyHandle, &ValueName, 0, REG_NONE, &TransactionInfo, sizeof(TransactionInfo)); if (!NT_SUCCESS(Status)) { TmpStatus = ZwDeleteKey(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); TmpStatus = NtClose(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); RtlFreeHeap(RtlGetProcessHeap(), 0, *OutContext); return Status; } return STATUS_RXACT_STATE_CREATED; } else { /* The key exited, get the default key value */ ValueDataLength = sizeof(TransactionInfo); Status = RtlpNtQueryValueKey(KeyHandle, &ValueType, &TransactionInfo, &ValueDataLength, 0); if (!NT_SUCCESS(Status)) { TmpStatus = NtClose(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); RtlFreeHeap(RtlGetProcessHeap(), 0, Context); return Status; } /* Check if the value date is valid */ if ((ValueDataLength != sizeof(TransactionInfo)) || (TransactionInfo.Revision != 1)) { TmpStatus = NtClose(KeyHandle); ASSERT(NT_SUCCESS(TmpStatus)); RtlFreeHeap(RtlGetProcessHeap(), 0, Context); return STATUS_UNKNOWN_REVISION; } /* Query the 'Log' key value */ RtlInitUnicodeString(&ValueName, L"Log"); Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValueBasicInformation, &KeyValueBasicInfo, sizeof(KeyValueBasicInfo), &Length); if (!NT_SUCCESS(Status)) { /* There is no 'Log', so we are done */ return STATUS_SUCCESS; } /* Check if the caller asked to commit the current state */ if (!Commit) { /* We have a log, that must be committed first! */ return STATUS_RXACT_COMMIT_NECESSARY; } /* Query the size of the 'Log' key value */ Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValueFullInformation, NULL, 0, &Length); if (Status != STATUS_BUFFER_TOO_SMALL) { return Status; } /* Allocate a buffer for the key value information */ KeyValueInformation = RtlAllocateHeap(RtlGetProcessHeap(), 0, Length); if (KeyValueInformation == NULL) { return STATUS_NO_MEMORY; } /* Query the 'Log' key value */ Status = ZwQueryValueKey(KeyHandle, &ValueName, KeyValueFullInformation, KeyValueInformation, Length, &Length); if (!NT_SUCCESS(Status)) { RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation); RtlFreeHeap(RtlGetProcessHeap(), 0, Context); return Status; } /* Set the Data pointer to the key value data */ Context->Data = (PRXACT_DATA)((PUCHAR)KeyValueInformation + KeyValueInformation->DataOffset); /* This is an old log, don't use handles when committing! */ Context->CanUseHandles = FALSE; /* Commit the data */ Status = RXactpCommit(Context); if (!NT_SUCCESS(Status)) { RtlFreeHeap(RtlGetProcessHeap(), 0, KeyValueInformation); RtlFreeHeap(RtlGetProcessHeap(), 0, Context); return Status; } /* Delete the old key */ Status = NtDeleteValueKey(KeyHandle, &ValueName); ASSERT(NT_SUCCESS(Status)); /* Set the data member to the allocated buffer, so it will get freed */ Context->Data = (PRXACT_DATA)KeyValueInformation; /* Abort the old transaction */ Status = RtlAbortRXact(Context); ASSERT(NT_SUCCESS(Status)); return Status; } }
BOOLEAN PreNotificationBlockSample( ) /*++ Routine Description: This sample shows how to block a registry operation in the pre-notification phase. Two keys are created. The create operations should succeed, but one is intercepted by the callback and failed with STATUS_ACCESS_DENIED. The same is done for two values. Return Value: TRUE if the sample completed successfully. --*/ { PCALLBACK_CONTEXT CallbackCtx = NULL; NTSTATUS Status; OBJECT_ATTRIBUTES KeyAttributes; UNICODE_STRING Name; HANDLE Key = NULL; HANDLE NotModifiedKey = NULL; DWORD ValueData = 0; BOOLEAN Success = FALSE; InfoPrint(""); InfoPrint("=== Pre-Notification Block Sample ===="); // // Create the callback context // CallbackCtx = CreateCallbackContext(CALLBACK_MODE_PRE_NOTIFICATION_BLOCK, CALLBACK_ALTITUDE); if (CallbackCtx == NULL) { goto Exit; } // // Register callback // Status = CmRegisterCallbackEx(Callback, &CallbackCtx->Altitude, g_DeviceObj->DriverObject, (PVOID) CallbackCtx, &CallbackCtx->Cookie, NULL); if (!NT_SUCCESS(Status)) { ErrorPrint("CmRegisterCallback failed. Status 0x%x", Status); goto Exit; } Success = TRUE; // // Create two keys. // Creating the "not modified" key will succeed. // Creating the other key will fail with STATUS_ACCESS_DENIED // RtlInitUnicodeString(&Name, NOT_MODIFIED_KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, g_RootKey, NULL); Status = ZwCreateKey(&NotModifiedKey, KEY_ALL_ACCESS, &KeyAttributes, 0, NULL, 0, NULL); if (Status != STATUS_SUCCESS) { ErrorPrint("ZwCreateKey returned unexpected status 0x%x", Status); Success = FALSE; } RtlInitUnicodeString(&Name, KEY_NAME); InitializeObjectAttributes(&KeyAttributes, &Name, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, g_RootKey, NULL); Status = ZwCreateKey(&Key, KEY_ALL_ACCESS, &KeyAttributes, 0, NULL, 0, NULL); if (Status != STATUS_ACCESS_DENIED) { ErrorPrint("ZwCreateKey returned unexpected status 0x%x", Status); Success = FALSE; } // // Set two values. // Setting the "not modified" value will succeed. // Setting the other value will fail with STATUS_ACCESS_DENIED. // RtlInitUnicodeString(&Name, NOT_MODIFIED_VALUE_NAME); Status = ZwSetValueKey(g_RootKey, &Name, 0, REG_DWORD, &ValueData, sizeof(ValueData)); if(Status != STATUS_SUCCESS) { ErrorPrint("ZwSetValue return unexpected status 0x%x", Status); Success = FALSE; } RtlInitUnicodeString(&Name, VALUE_NAME); Status = ZwSetValueKey(g_RootKey, &Name, 0, REG_DWORD, &ValueData, sizeof(ValueData)); if(Status != STATUS_ACCESS_DENIED) { ErrorPrint("ZwSetValue return unexpected status 0x%x", Status); Success = FALSE; } // // Unregister the callback // Status = CmUnRegisterCallback(CallbackCtx->Cookie); if (!NT_SUCCESS(Status)) { ErrorPrint("CmUnRegisterCallback failed. Status 0x%x", Status); Success = FALSE; } Exit: // // Clean up // if (Key != NULL) { ZwDeleteKey(Key); ZwClose(Key); } if (NotModifiedKey != NULL) { ZwDeleteKey(NotModifiedKey); ZwClose(NotModifiedKey); } RtlInitUnicodeString(&Name, VALUE_NAME); ZwDeleteValueKey(g_RootKey, &Name); RtlInitUnicodeString(&Name, NOT_MODIFIED_VALUE_NAME); ZwDeleteValueKey(g_RootKey, &Name); if (CallbackCtx != NULL) { ExFreePoolWithTag(CallbackCtx, REGFLTR_CONTEXT_POOL_TAG); } if (Success) { InfoPrint("Pre-Notification Block Sample succeeded."); } else { ErrorPrint("Pre-Notification Block Sample FAILED."); } return Success; }