Controladores del kernel de Windows - Errores comunes - IRQL

Este artículo está dirigido a aquellos que acaban de comenzar a desarrollar controladores de kernel para Windows. ¿Por centésima vez ves el odiado IRQL_NOT_LESS_OR_EQUAL y esta triste carita sonriente? Entonces, por favor, ve debajo del gato.





, , IRQL , , Windows.



, , - PID-.





KSPIN_LOCK SharedDataLock;

NTSTATUS SomeFunction(_In_ HANDLE ProcessId)
{
    KIRQL OriginalIrql;

    NTSTATUS status = STATUS_UNSUCCESSFUL;

    // lock shared data access
    KeAcquireSpinLock(&SharedDataLock, &OriginalIrql);

    // some code, which works with shared data
    PVOID data = GetProcessSharedData(ProcessId);
    NT_ASSERT("GetProcessSharedData() must always return shared data.", data);

    PEPROCESS Process = NULL;
    // next we need to get process image name
    status = PsLookupProcessByProcessId(
									ProcessId,
									&Process
                                );

    if ( !NT_SUCCESS( status ) )
    {
        goto LOCK_RELEASE;
    }

    PUNICODE_STRING ProcessImage = NULL;
    status = GetProcessImagename(Process, &ProcessImage);
    if ( !NT_SUCCESS( status ) )
    {
        goto PROCESS_LINK_DEREF;
    }

    // generate some event for our log
    GenerateEvent( ProcessImage, data );

PROCESS_LINK_DEREF:
	ObDereferenceObject(Process);
LOCK_RELEASE:     // release lock     
	KeReleaseSpinLock(&SharedDataLock, OriginalIrql);
	return status;
}
      
      



, , , . , .





?





PsLookupProcessByProcessId()



– : IRQL <= APC_LEVEL.





, BSOD IRQL_NOT_LESS_OR_EQUAL.





, . , , IRQL , .





, — :





KSPIN_LOCK SharedDataLock;

VOID SetIrql(_In_ KIRQL Irql)
{
	if ( KeGetCurrentIrql() > Irql )
		KeLowerIrql(Irql);
	else if ( KeGetCurrentIrql() < Irql )
		KzRaiseIrql(Irql);
}

NTSTATUS SomeFunction(_In_ HANDLE ProcessId)
{
    KIRQL OriginalIrql;

    NTSTATUS status = STATUS_UNSUCCESSFUL;

    // lock shared data access
    KeAcquireSpinLock(&SharedDataLock, &OriginalIrql);

    // some code, which works with shared data
    PVOID data = GetProcessSharedData(ProcessId);
    NT_ASSERT("GetProcessSharedData() must always return shared data.", data);

    SetIrql(APC_LEVEL);

    PEPROCESS Process = NULL;
    // next we need to get process image name
    status = PsLookupProcessByProcessId(
                                     ProcessId,
                                     &Process
                                );

    SetIrql(DISPATCH_LEVEL);

    if ( !NT_SUCCESS( status ) )
    {
        goto LOCK_RELEASE;
    }

    PUNICODE_STRING ProcessImage = NULL;
    status = GetProcessImagename(Process, &ProcessImage);
    if ( !NT_SUCCESS( status ) )
    {
        goto PROCESS_LINK_DEREF;
    }

    // generate some event for our log
    GenerateEvent( ProcessImage, data );

PROCESS_LINK_DEREF:
	ObDereferenceObject(Process);
LOCK_RELEASE:
  // release lock     
	KeReleaseSpinLock(&SharedDataLock, OriginalIrql);
	return status;
}
      
      



, . , . , , 1 1000 , , , .





, :

« IRQL , , !»





:





- IRQL = APC_LEVEL, . IRQL DISPATCH_LEVEL, APC_LEVEL, .





, , :





KSPIN_LOCK SharedDataLock;

_IRQL_requires_max_(APC_LEVEL)
NTSTATUS SomeFunction(_In_ HANDLE ProcessId)
{
    NTSTATUS status = STATUS_UNSUCCESSFUL;

    PEPROCESS Process = NULL;
    // next we need to get process image name
    status = PsLookupProcessByProcessId(
                                   ProcessId,
                                   &Process
                                );

    if ( !NT_SUCCESS( status ) )
    {
        goto EXIT_ROUTINE;
    }

    PUNICODE_STRING ProcessImage = NULL;
    status = GetProcessImagename(Process, &ProcessImage);
    if ( !NT_SUCCESS( status ) )
    {
        goto PROCESS_LINK_DEREF;
    }

    // lock shared data access
    KeAcquireSpinLock(&SharedDataLock, &OriginalIrql);

    // some code, which works with shared data
    PVOID data = GetProcessSharedData(ProcessId);
    NT_ASSERT("GetProcessSharedData() must always return shared data.", data);

    // generate some event for our log
    GenerateEvent( ProcessImage, data );

    // release lock
    KeReleaseSpinLock(&SharedDataLock, OriginalIrql);
		
PROCESS_LINK_DEREF:
	ObDereferenceObject(Process);
EXIT_ROUTINE:
	return status;
}	
      
      



SetIrql() 2- , , .. , .





, SAL, :





MSDN SAL 2.0





Microsoft whitepaper( ) , :





MSDN Managing Hardware Priorities





, - - - Api, IRQL, WorkItem’. , .








All Articles