Ejemplo n.º 1
0
NTSTATUS
RegistryDeleteValue(
    IN  PHANDLE         Key,
    IN  PCHAR           Name
    )
{
    ANSI_STRING         Ansi;
    UNICODE_STRING      Unicode;
    NTSTATUS            status;

    RtlInitAnsiString(&Ansi, Name);

    status = RtlAnsiStringToUnicodeString(&Unicode, &Ansi, TRUE);
    if (!NT_SUCCESS(status))
        goto fail1;

    status = ZwDeleteValueKey(Key, &Unicode);
    if (!NT_SUCCESS(status))
        goto fail2;

    RtlFreeUnicodeString(&Unicode);

    return STATUS_SUCCESS;

fail2:
    RtlFreeUnicodeString(&Unicode);

fail1:
    return status;
}
Ejemplo n.º 2
0
void RegDeleteValueKey(LPWSTR KeyName, LPWSTR ValueName)
{
	OBJECT_ATTRIBUTES objectAttributes;
	UNICODE_STRING usKeyName,usValueName;
	NTSTATUS ntStatus;
	HANDLE hRegister;
	RtlInitUnicodeString(&usKeyName, KeyName);
	RtlInitUnicodeString(&usValueName, ValueName);
	InitializeObjectAttributes(&objectAttributes,
	                           &usKeyName,
	                           OBJ_CASE_INSENSITIVE,//对大小写敏感
	                           NULL,
	                           NULL );
	ntStatus = ZwOpenKey(&hRegister, KEY_ALL_ACCESS, &objectAttributes);
	if (NT_SUCCESS(ntStatus))
	{
		ntStatus = ZwDeleteValueKey(hRegister,&usValueName);
		ZwFlushKey(hRegister);
		ZwClose(hRegister);
		DbgPrint("ZwDeleteValueKey success!\n");
	}
	else
	{
		DbgPrint("ZwDeleteValueKey failed!\n");
	}
}
Ejemplo n.º 3
0
static SshRegBool
ssh_registry_platform_delete_value(SshRegKey registry_key,
                                   SshRegUnicodeString value)
{
  SshRegBool ret_value = FALSE;

  SSH_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

  if (NT_SUCCESS(ZwDeleteValueKey(registry_key, value)))
    ret_value = TRUE;

  return ret_value;
}
Ejemplo n.º 4
0
BOOLEAN HidePortName(IN PC0C_FDOPORT_EXTENSION pDevExt)
{
    BOOLEAN res;
    HANDLE hKey;
    NTSTATUS status;

    if (pDevExt->pIoPortLocal->isComClass)
        return TRUE;

    res = TRUE;

    status = IoOpenDeviceRegistryKey(pDevExt->pIoPortLocal->pPhDevObj,
                                     PLUGPLAY_REGKEY_DEVICE,
                                     STANDARD_RIGHTS_WRITE,
                                     &hKey);

    if (NT_SUCCESS(status)) {
        UNICODE_STRING keyName;

        RtlInitUnicodeString(&keyName, L"PortName");

        status = ZwDeleteValueKey(hKey, &keyName);

        if (NT_SUCCESS(status)) {
            Trace0((PC0C_COMMON_EXTENSION)pDevExt, L"Hidden PORTNAME");
        }
        else if ((pDevExt->shown & C0C_SHOW_PORTNAME) != 0) {
            res = FALSE;
            Trace0((PC0C_COMMON_EXTENSION)pDevExt, L"HidePortName ZwDeleteValueKey(PortName) FAIL");
        }

        ZwClose(hKey);
    }
    else if ((pDevExt->shown & C0C_SHOW_PORTNAME) != 0) {
        res = FALSE;
        Trace0((PC0C_COMMON_EXTENSION)pDevExt, L"HidePortName IoOpenDeviceRegistryKey(PLUGPLAY_REGKEY_DEVICE) FAIL");
    }

    pDevExt->shown &= ~C0C_SHOW_PORTNAME;

    return res;
}
Ejemplo n.º 5
0
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;

}
Ejemplo n.º 6
0
BOOLEAN 
SetObjectContextSample(
    )
/*++

Routine Description:

    This sample shows how a registry callback can associate a context on
    a registry object using CmSetCallbackObjectContext. 

    This context is available in the ObjectContext field of the 
    REG_Xxx_KEY_INFORMATION data structures. The registry object is a handle
    to a key and not the registry key itself. When the handle is closed
    or the callback is unregistered, the callback will receive a 
    RegNtCallbackObjectContextCleanup notification to give a chance to 
    clean up the context.

Return Value:

    TRUE if the sample completed successfully.

--*/
{

    PCALLBACK_CONTEXT CallbackCtx = NULL;
    NTSTATUS Status;
    UNICODE_STRING Name;
    OBJECT_ATTRIBUTES KeyAttributes;
    HANDLE RootKeyWithContext = NULL;
    DWORD ValueData = 0;
    BOOLEAN Success = FALSE;


    InfoPrint("");
    InfoPrint("=== Set Object Context Sample ====");

    //
    // Create the callback context
    //

    CallbackCtx = CreateCallbackContext(CALLBACK_MODE_SET_OBJECT_CONTEXT,
                                         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;
    
    //
    // Open the root key again. The callback will associate an object
    // context with the RootKeyWithContext handle.
    //

    RtlInitUnicodeString(&Name, ROOT_KEY_ABS_PATH);
    InitializeObjectAttributes(&KeyAttributes,
                               &Name,
                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                               NULL,
                               NULL);
    
    Status = ZwOpenKey(&RootKeyWithContext,
                       KEY_ALL_ACCESS,
                       &KeyAttributes);

    if (!NT_SUCCESS(Status)) {
        ErrorPrint("ZwOpenKey on root key failed. Status 0x%x", Status);
        Success = FALSE;
    }

    //
    // Set value using both the g_RootKey handle and the RootKeyWithContext
    // handle.
    //

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

    if (RootKeyWithContext != NULL) {
        Status = ZwSetValueKey(RootKeyWithContext,
                               &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);
    }

    //
    // Check that the RegNtCallbackObjectContextCleanup notification was
    // received when we unregistered the callback.
    //

    if (CallbackCtx->ContextCleanupCount != 1) {
        ErrorPrint("Callback was not invoked for a context cleanup notification.");
        Success = FALSE;
    } 

    //
    // Check that there were two notifications that had the object context set.
    // These are the pre and post set value using the RootKeyWithContext handle.
    //
    
    if (CallbackCtx->NotificationWithContextCount != 2) {
        ErrorPrint("Callback OperationWithContext count expected 2, instead it was %d",
                   CallbackCtx->NotificationWithContextCount);
        Success = FALSE;
    } 

    //
    // Check that there were two notifications that did not have the object 
    // context set. These are the pre and post set value using the 
    // g_RootKey handle.
    //
    
    if (CallbackCtx->NotificationWithNoContextCount != 2) {
        ErrorPrint("Callback OperationWithNoContext count expected 2, instead it was %d",
                   CallbackCtx->NotificationWithNoContextCount);
        Success = FALSE;
    } 

  Exit:
    
    if (Success == TRUE) {
        InfoPrint("Set Object Context Sample Succeeded.");
    } else {
        ErrorPrint("Set Object Context Sample FAILED.");
    }

    //
    // Clean up
    //
    
    RtlInitUnicodeString(&Name, VALUE_NAME);
    ZwDeleteValueKey(g_RootKey, &Name);
    
    if (RootKeyWithContext != NULL) {
        ZwClose(RootKeyWithContext);
    }

    if (CallbackCtx != NULL) {
        ExFreePoolWithTag(CallbackCtx, REGFLTR_CONTEXT_POOL_TAG);
    }

    return Success;
}
Ejemplo n.º 7
0
NTSTATUS 
CallbackCapture(
    _In_ PCALLBACK_CONTEXT CallbackCtx,
    _In_ REG_NOTIFY_CLASS NotifyClass,
    _Inout_ PVOID Argument2
)
/*++

Routine Description:

    This helper callback routine shows how to capture a buffer and a
    unicode string with the name of a value. The bulk of the work is down
    in the helper capture routines: CaptureBuffer and CaptureUnicodeString.

    In the pre-notification phase, we bypass the set value and delete value
    operations and complete them manually by calling ZwSetValueKey and 
    ZwDeleteValueKey. 
    
Arguments:

    CallbackContext - The value that the driver passed to the Context parameter
        of CmRegisterCallbackEx when it registers this callback routine.

    NotifyClass - A REG_NOTIFY_CLASS typed value that identifies the type of 
        registry operation that is being performed and whether the callback
        is being called in the pre or post phase of processing.

    Argument2 - A pointer to a structure that contains information specific
        to the type of the registry operation. The structure type depends
        on the REG_NOTIFY_CLASS value of Argument1. 

Return Value:

    NTSTATUS

--*/
{
    NTSTATUS Status = STATUS_SUCCESS;
    PREG_SET_VALUE_KEY_INFORMATION PreSetValueInfo;
    PREG_DELETE_VALUE_KEY_INFORMATION PreDeleteValueInfo;
    HANDLE RootKey = NULL;
    PVOID LocalData = NULL;
    PVOID Data = NULL;
    UNICODE_STRING LocalValueName = {0};
    PUNICODE_STRING ValueName = NULL;
    KPROCESSOR_MODE Mode = KernelMode;
    
    UNREFERENCED_PARAMETER(CallbackCtx);
    
    switch(NotifyClass) {
        
        case RegNtPreSetValueKey:

            PreSetValueInfo = (PREG_SET_VALUE_KEY_INFORMATION) Argument2;

            //
            // REG_SET_VALUE_KEY_INFORMATION is a partially captured structure.
            // The value name is captured but the data is not. Since we are
            // passing the data to a zw* method, we need to capture it.
            //
            // *Note: as of win8, the data buffer is captured as well
            // by the registry.
            //
            
            Mode = ExGetPreviousMode();

            if (!g_IsWin8OrGreater && (Mode == UserMode)) {
                Status = CaptureBuffer(&LocalData, 
                                       PreSetValueInfo->Data, 
                                       PreSetValueInfo->DataSize, 
                                       REGFLTR_CAPTURE_POOL_TAG);
                if (!NT_SUCCESS(Status)) {
                    break;
                }
                Data = LocalData;
            } else {
                Data = PreSetValueInfo->Data;
            }

            //
            // Get a handle to the root key the value is being created under.
            // This is in PreInfo->Object.
            //
            
            Status = ObOpenObjectByPointer(PreSetValueInfo->Object,
                                           OBJ_KERNEL_HANDLE,
                                           NULL,
                                           KEY_ALL_ACCESS,
                                           NULL,
                                           KernelMode,
                                           &RootKey);

            if (!NT_SUCCESS (Status)) {
                ErrorPrint("ObObjectByPointer failed. Status 0x%x", Status);
                break;
            } 

            //
            // Set the value.
            //
            
            Status = ZwSetValueKey(RootKey,
                                   PreSetValueInfo->ValueName,
                                   0,
                                   PreSetValueInfo->Type,
                                   Data,
                                   PreSetValueInfo->DataSize);
            
            if(!NT_SUCCESS(Status)) {
                ErrorPrint("ZwSetValue in CallbackModify failed. Status 0x%x", 
                           Status);
                ZwClose(RootKey);
                break;
            }

            //
            // Finally return STATUS_CALLBACK_BYPASS to tell the registry
            // not to proceed with the original registry operation and to return
            // STATUS_SUCCESS to the caller.
            //

            InfoPrint("\tCallback: Set value %wZ bypassed.", PreSetValueInfo->ValueName);
            Status = STATUS_CALLBACK_BYPASS;
            ZwClose(RootKey);
            break;
           
        case RegNtPreDeleteValueKey:

            PreDeleteValueInfo = (PREG_DELETE_VALUE_KEY_INFORMATION) Argument2;

            //
            // REG_DELETE_VALUE_KEY_INFORMATION is a partially captured 
            // structure. The value name's buffer is not captured. Since we are
            // passing the name to a zw* method, we need to capture it.
            //
            // *Note: as of Win8, the data buffer is captured already
            // by the registry.
            //
            
            Mode = ExGetPreviousMode();

            if (!g_IsWin8OrGreater && (Mode == UserMode)) {
                Status = CaptureUnicodeString(&LocalValueName, 
                                              PreDeleteValueInfo->ValueName,
                                              REGFLTR_CAPTURE_POOL_TAG);
                if (!NT_SUCCESS(Status)) {
                    break;
                }
                ValueName = &LocalValueName;
            } else {
                ValueName = PreDeleteValueInfo->ValueName;
            }

            //
            // Get a handle to the root key the value is being created under.
            // This is in PreInfo->Object.
            //
            
            Status = ObOpenObjectByPointer(PreDeleteValueInfo->Object,
                                           OBJ_KERNEL_HANDLE,
                                           NULL,
                                           KEY_ALL_ACCESS,
                                           NULL,
                                           KernelMode,
                                           &RootKey);

            if (!NT_SUCCESS (Status)) {
                ErrorPrint("ObObjectByPointer failed. Status 0x%x", Status);
                break;
            } 

            //
            // Set the value.
            //
            
            Status = ZwDeleteValueKey(RootKey,
                                      ValueName);
            
            if(!NT_SUCCESS(Status)) {
                ErrorPrint("ZwDeleteValue failed. Status 0x%x", 
                           Status);
                ZwClose(RootKey);
                break;
            }

            //
            // Finally return STATUS_CALLBACK_BYPASS to tell the registry
            // not to proceed with the original registry operation and to return
            // STATUS_SUCCESS to the caller.
            //

            InfoPrint("\tCallback: Delete value %S bypassed.", ValueName->Buffer);
            Status = STATUS_CALLBACK_BYPASS;
            ZwClose(RootKey);
            break;

        default:
            //
            // Do nothing for other notifications
            //
            break;
    }

    //
    // Free buffers used for capturing user mode values.
    //
    
    if (LocalData != NULL){
        FreeCapturedBuffer(LocalData, REGFLTR_CAPTURE_POOL_TAG);
    }

    if (LocalValueName.Buffer != NULL) {
        FreeCapturedUnicodeString(&LocalValueName, REGFLTR_CAPTURE_POOL_TAG);
    }

    return Status;
}
Ejemplo n.º 8
0
NTSTATUS SetLowerFilters(PUNICODE_STRING szUName,ULONG uFlag)
{
    //设置底层过滤函数,完成对注册表的处理

	UNICODE_STRING dst,src,ValueName;
	HANDLE hRegister,hSubKey;
	WCHAR dst_buf[256];

	//初始化UNICODE_STRING字符串
	RtlInitEmptyUnicodeString(&dst,dst_buf,256*sizeof(WCHAR));
	RtlInitUnicodeString(&src,USBSTOR);
	RtlCopyUnicodeString(&dst,&src);
	RtlAppendUnicodeStringToString(&dst,szUName);

	OBJECT_ATTRIBUTES objectAttributes;

	//初始化objectAttributes
	InitializeObjectAttributes(&objectAttributes,
		&dst,
		OBJ_CASE_INSENSITIVE,//对大小写敏感
		NULL,
		NULL );

	//打开注册表
	NTSTATUS ntStatus = ZwOpenKey( &hRegister,
		KEY_ALL_ACCESS,
		&objectAttributes);

    //打开注册表成功
	if (NT_SUCCESS(ntStatus))
	{
		DbgPrint("Open register successfully\n");
	}

	RtlInitUnicodeString(&ValueName,L"LowerFilters");
	PWCHAR strValue=L"USBFilter";

	ULONG ulSize;

	//第一次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的长度
	ZwQueryKey(hRegister,
		KeyFullInformation,
		NULL,
		0,
		&ulSize);

	PKEY_FULL_INFORMATION pfi =
		(PKEY_FULL_INFORMATION)
		ExAllocatePool(PagedPool,ulSize);

	//第二次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的数据
	ZwQueryKey(hRegister,
		KeyFullInformation,
		pfi,
		ulSize,
		&ulSize);

	for (ULONG i=0;i<pfi->SubKeys;i++)
	{
		//第一次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的长度
		ZwEnumerateKey(hRegister,
			i,
			KeyBasicInformation,
			NULL,
			0,
			&ulSize);

		PKEY_BASIC_INFORMATION pbi =
			(PKEY_BASIC_INFORMATION)
			ExAllocatePool(PagedPool,ulSize);

		//第二次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的数据
		ZwEnumerateKey(hRegister,
			i,
			KeyBasicInformation,
			pbi,
			ulSize,
			&ulSize);

		UNICODE_STRING uniKeyName;
		uniKeyName.Length =
			uniKeyName.MaximumLength =
			(USHORT)pbi->NameLength;

		uniKeyName.Buffer = pbi->Name;

		WCHAR bufTmp[256];

		//初始化值
		RtlInitEmptyUnicodeString(&src,bufTmp,256*sizeof(WCHAR));
		RtlCopyUnicodeString(&src,&dst);

		UNICODE_STRING szX;
		RtlInitUnicodeString(&szX,L"\\");
		RtlAppendUnicodeStringToString(&src,&szX),
			RtlAppendUnicodeStringToString(&src,&uniKeyName);

        //初始化ObjectAttributes
		InitializeObjectAttributes(&objectAttributes,
			&src,
			OBJ_CASE_INSENSITIVE,//对大小写敏感
			NULL,
			NULL );

        //打开注册表
		ZwOpenKey( &hSubKey,
			KEY_ALL_ACCESS,
			&objectAttributes);

        //uFlag为0则删除注册表键值,否则设置注册表键值
		if(uFlag==0)
		{
			ntStatus=ZwDeleteValueKey(hSubKey,&ValueName);
		}
		else
		{
		ntStatus=ZwSetValueKey(hSubKey,&ValueName,0,REG_SZ,strValue,wcslen(strValue)*2+2);
		}

		//成功的话
		if (NT_SUCCESS(ntStatus))
		{
			DbgPrint("Charge Value successfully\n");
		}
		else
			DbgPrint("Charge Value failed!\n");

		DbgPrint("The %d sub item name:%wZ\n",i,&src);

        //回收内存
		ExFreePool(pbi);

		//关闭句柄
		ZwClose(hSubKey);
	}

	ExFreePool(pfi);
	ZwClose(hRegister);

	return STATUS_SUCCESS;
}
Ejemplo n.º 9
0
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(
            &regKey,
            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;
}
Ejemplo n.º 10
0
 //在注册表子项中设置LowerFilters子项
NTSTATUS SetLowerFilters(PUNICODE_STRING szUName,ULONG uFlag)
{
	UNICODE_STRING dst,src,ValueName;
	HANDLE hRegister,hSubKey;
	WCHAR dst_buf[256];

	//初始化UNICODE_STRING字符串
	RtlInitEmptyUnicodeString(&dst,dst_buf,256*sizeof(WCHAR));
	//初始化src为U盘注册表位置
	RtlInitUnicodeString(&src,USBSTOR);
	RtlCopyUnicodeString(&dst,&src);

	//将U盘名字追加到注册表位置末尾,为选中U盘的实际注册表位置
	RtlAppendUnicodeStringToString(&dst,szUName);

	OBJECT_ATTRIBUTES objectAttributes;

	//初始化objectAttributes
	InitializeObjectAttributes(&objectAttributes,
		&dst,               //文件名
		OBJ_CASE_INSENSITIVE,//对大小写敏感
		NULL,
		NULL );

	//打开注册表
	NTSTATUS ntStatus = ZwOpenKey( &hRegister,   //返回被打开的句柄
		KEY_ALL_ACCESS,         //打开权限,一般都这么设置
		&objectAttributes);

    //打开注册表成功
	if (NT_SUCCESS(ntStatus))
	{
		DbgPrint("Open register successfully\n");
	}

    //要在注册表子项下添加LowerFilters的表项
	RtlInitUnicodeString(&ValueName,L"LowerFilters");

	//键值设为过滤类名,如果随便设一个会导致U盘连接状态但是不能查看到
	PWCHAR strValue=L"UsbFilter";

	ULONG ulSize;

	//第一次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的长度(因为是变长的)
	ZwQueryKey(hRegister,
		KeyFullInformation,  //查询类别,一般都这么设置
		NULL,
		0,
		&ulSize);         //返回数据KEY_FULL_INFORMATION的长度

	PKEY_FULL_INFORMATION pfi =
		(PKEY_FULL_INFORMATION)
		ExAllocatePool(PagedPool,ulSize);

	//第二次调用ZwQueryKey为了获取KEY_FULL_INFORMATION数据的数据
	ZwQueryKey(hRegister,
		KeyFullInformation,
		pfi,      //查询数据的指针
		ulSize,   //数据长度
		&ulSize);

    //ZwQueryKey的作用主要就是获得某注册表究竟有多少个子项
    //而ZwEnumerateKey的作用主要是针对第几个子项获取该子项的具体信息

	for (ULONG i=0;i<pfi->SubKeys;i++)
	{
		//第一次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的长度
		ZwEnumerateKey(hRegister,
			i,
			KeyBasicInformation,
			NULL,
			0,
			&ulSize);

		PKEY_BASIC_INFORMATION pbi =
			(PKEY_BASIC_INFORMATION)
			ExAllocatePool(PagedPool,ulSize);

		//第二次调用ZwEnumerateKey为了获取KEY_BASIC_INFORMATION数据的数据
		ZwEnumerateKey(hRegister,
			i,
			KeyBasicInformation,
			pbi,
			ulSize,
			&ulSize);

		UNICODE_STRING uniKeyName;

		//获取子项名字的长度
		uniKeyName.Length =
			uniKeyName.MaximumLength =
			(USHORT)pbi->NameLength;

		uniKeyName.Buffer = pbi->Name;

		WCHAR bufTmp[256];

		//初始化值
		RtlInitEmptyUnicodeString(&src,bufTmp,256*sizeof(WCHAR));
		RtlCopyUnicodeString(&src,&dst);

		UNICODE_STRING szX;
		RtlInitUnicodeString(&szX,L"\\");
		RtlAppendUnicodeStringToString(&src,&szX),

		//这里就得到注册表子项名字的具体路径名,保存在src中
        RtlAppendUnicodeStringToString(&src,&uniKeyName);

        //初始化ObjectAttributes
		InitializeObjectAttributes(&objectAttributes,
			&src,
			OBJ_CASE_INSENSITIVE,//对大小写敏感
			NULL,
			NULL );

        //打开注册表
		ZwOpenKey( &hSubKey,
			KEY_ALL_ACCESS,
			&objectAttributes);

        //uFlag为0则删除注册表键值(既关写保护),否则设置注册表键值(既开写保护)
		if(uFlag==0)
		{
			ntStatus=ZwDeleteValueKey(hSubKey,&ValueName);
		}
		else
		{
		ntStatus=ZwSetValueKey(hSubKey,&ValueName,0,REG_SZ,strValue,wcslen(strValue)*2+2);
		}

		//成功的话
		if (NT_SUCCESS(ntStatus))
		{
			DbgPrint("Charge Value successfully\n");
		}
		else
			DbgPrint("Charge Value failed!\n");

		DbgPrint("The %d sub item name:%wZ\n",i,&src);

        //回收内存
		ExFreePool(pbi);

		//关闭句柄
		ZwClose(hSubKey);
	}

	ExFreePool(pfi);
	ZwClose(hRegister);

	return STATUS_SUCCESS;
}
Ejemplo n.º 11
0
NTSTATUS
NdasPortFdoRegDeleteLogicalUnit(
	__in PNDASPORT_FDO_EXTENSION FdoExtension,
	__in NDAS_LOGICALUNIT_ADDRESS LogicalUnitAddress)
{
	NTSTATUS status, status2;
	HANDLE keyHandle;
	WCHAR valueNameBuffer[32];
	UNICODE_STRING valueName;

	PAGED_CODE();

	keyHandle = NULL;
	status = NdasPortFdoOpenRegistryKey(
		FdoExtension,
		NDASPORT_FDO_REGKEY_LOGICALUNIT_LIST,
		KEY_WRITE,
		&keyHandle);

	if (!NT_SUCCESS(status))
	{
		NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR,
			"IoOpenDeviceRegistryKey failed, status=%X, fdo=%p\n", 
			status,
			FdoExtension->DeviceObject);
		return status;
	}

	RtlInitEmptyUnicodeString(
		&valueName, 
		valueNameBuffer, 
		sizeof(valueNameBuffer));

	status2 = RtlUnicodeStringPrintf(
		&valueName, 
		L"LU%08X",
		LogicalUnitAddress);

	ASSERT(NT_SUCCESS(status2));

	status = ZwDeleteValueKey(
		keyHandle,
		&valueName);

	if (!NT_SUCCESS(status))
	{
		NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_ERROR,
			"ZwDeleteValueKey failed, keyHandle=%p, value=%wZ, status=%X\n", 
			keyHandle, &valueName, status);
		goto ret;
	}

	status = STATUS_SUCCESS;

	goto ret;

ret:
	status2 = ZwClose(keyHandle);

	ASSERT(NT_SUCCESS(status2));
	if (!NT_SUCCESS(status2))
	{
		NdasPortTrace(NDASPORT_FDO_IOCTL, TRACE_LEVEL_WARNING,
			"ZwClose failed, keyHandle=%p, status=%X\n", 
			keyHandle, status2);
	}

	return status;
}
Ejemplo n.º 12
0
VOID
IopSaveBootLogToFile(VOID)
{
    PKEY_VALUE_PARTIAL_INFORMATION KeyInfo;
    WCHAR ValueNameBuffer[8];
    OBJECT_ATTRIBUTES ObjectAttributes;
    UNICODE_STRING KeyName;
    UNICODE_STRING ValueName;
    HANDLE KeyHandle;
    ULONG BufferSize;
    ULONG ResultLength;
    ULONG i;
    NTSTATUS Status;

    if (IopBootLogCreate == FALSE)
        return;

    DPRINT("IopSaveBootLogToFile() called\n");

    ExAcquireResourceExclusiveLite(&IopBootLogResource, TRUE);

    Status = IopCreateLogFile();
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("IopCreateLogFile() failed (Status %lx)\n", Status);
        ExReleaseResourceLite(&IopBootLogResource);
        return;
    }

    //Status = IopWriteLogFile(L"ReactOS "KERNEL_VERSION_STR);

    if (!NT_SUCCESS(Status))
    {
        DPRINT1("IopWriteLogFile() failed (Status %lx)\n", Status);
        ExReleaseResourceLite(&IopBootLogResource);
        return;
    }

    Status = IopWriteLogFile(NULL);
    if (!NT_SUCCESS(Status))
    {
        DPRINT1("IopWriteLogFile() failed (Status %lx)\n", Status);
        ExReleaseResourceLite(&IopBootLogResource);
        return;
    }


    BufferSize = sizeof(KEY_VALUE_PARTIAL_INFORMATION) + 256 * sizeof(WCHAR);
    KeyInfo = ExAllocatePool(PagedPool,
                             BufferSize);
    if (KeyInfo == NULL)
    {
        ExReleaseResourceLite(&IopBootLogResource);
        return;
    }

    RtlInitUnicodeString(&KeyName,
                         L"\\Registry\\Machine\\System\\CurrentControlSet\\BootLog");
    InitializeObjectAttributes(&ObjectAttributes,
                               &KeyName,
                               OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);
    Status = ZwOpenKey(&KeyHandle,
                       KEY_ALL_ACCESS,
                       &ObjectAttributes);
    if (!NT_SUCCESS(Status))
    {
        ExFreePool(KeyInfo);
        ExReleaseResourceLite(&IopBootLogResource);
        return;
    }

    for (i = 0; ; i++)
    {
        swprintf(ValueNameBuffer,
                 L"%lu", i);

        RtlInitUnicodeString(&ValueName,
                             ValueNameBuffer);

        Status = ZwQueryValueKey(KeyHandle,
                                 &ValueName,
                                 KeyValuePartialInformation,
                                 KeyInfo,
                                 BufferSize,
                                 &ResultLength);
        if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
        {
            break;
        }

        if (!NT_SUCCESS(Status))
        {
            ZwClose(KeyHandle);
            ExFreePool(KeyInfo);
            ExReleaseResourceLite(&IopBootLogResource);
            return;
        }

        Status = IopWriteLogFile((PWSTR)&KeyInfo->Data);
        if (!NT_SUCCESS(Status))
        {
            ZwClose(KeyHandle);
            ExFreePool(KeyInfo);
            ExReleaseResourceLite(&IopBootLogResource);
            return;
        }

        /* Delete keys */
        ZwDeleteValueKey(KeyHandle,
                         &ValueName);
    }

    ZwClose(KeyHandle);

    ExFreePool(KeyInfo);

    IopLogFileEnabled = TRUE;
    ExReleaseResourceLite(&IopBootLogResource);

    DPRINT("IopSaveBootLogToFile() done\n");
}
Ejemplo n.º 13
0
NTSTATUS
IopWriteResourceList(
    HANDLE ResourceMapKey,
    PUNICODE_STRING ClassName,
    PUNICODE_STRING DriverName,
    PUNICODE_STRING DeviceName,
    PCM_RESOURCE_LIST ResourceList,
    ULONG ResourceListSize
    )

/*++

Routine Description:

    This routine takes a resourcelist and stores it in the registry resource
    map, using the ClassName, DriverName and DeviceName as the path of the
    key to store it in.

Arguments:

    ResourceMapKey - Handle to the root of the resource map.

    ClassName - Pointer to a Unicode String that contains the name of the Class
        for this resource list.

    DriverName - Pointer to a Unicode String that contains the name of the
        Driver for this resource list.

    DeviceName - Pointer to a Unicode String that contains the name of the
        Device for this resource list.

    ResourceList - P to the resource list.

    ResourceListSize - Value determining the size of the resource list.

Return Value:

    The status returned is the final completion status of the operation.

--*/


{
    NTSTATUS status;
    HANDLE classKeyHandle;
    HANDLE driverKeyHandle;

    PAGED_CODE();

    status = IopOpenRegistryKey( &classKeyHandle,
                                 ResourceMapKey,
                                 ClassName,
                                 KEY_READ | KEY_WRITE,
                                 TRUE );

    if (NT_SUCCESS( status )) {

        //
        // Take the resulting name to create the key.
        //

        status = IopOpenRegistryKey( &driverKeyHandle,
                                     classKeyHandle,
                                     DriverName,
                                     KEY_READ | KEY_WRITE,
                                     TRUE );

        ZwClose( classKeyHandle );


        if (NT_SUCCESS( status )) {

            //
            // With this key handle, we can now store the required information
            // in the value entries of the key.
            //

            //
            // Store the device name as a value name and the device information
            // as the rest of the data.
            // Only store the information if the CM_RESOURCE_LIST was present.
            //

            if (ResourceList->Count == 0) {

                status = ZwDeleteValueKey( driverKeyHandle,
                                           DeviceName );

            } else {

                status = ZwSetValueKey( driverKeyHandle,
                                        DeviceName,
                                        0L,
                                        REG_RESOURCE_LIST,
                                        ResourceList,
                                        ResourceListSize );

            }

            ZwClose( driverKeyHandle );

        }
    }

    return status;
}
Ejemplo n.º 14
0
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;
}
Ejemplo n.º 15
0
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;
    
}