PreviousMode

사용자 모드 애플리케이션이 네이티브 시스템 서비스 루틴의 Nt 또는 Zw 버전을 호출하는 경우 시스템 호출 메커니즘은 호출 스레드를 커널 모드로 트래핑합니다. 매개 변수 값이 사용자 모드에서 시작되었음을 나타내기 위해 시스템 호출에 대한 트랩 처리기는 호출자의 스레드 개체에 있는 PreviousMode 필드를 UserMode로 설정합니다. 네이티브 시스템 서비스 루틴은 호출 스레드의 PreviousMode 필드를 검사하여 매개 변수가 사용자 모드 원본에서 온 것인지 여부를 확인합니다.

커널 모드 드라이버가 네이티브 시스템 서비스 루틴을 호출하고 커널 모드 원본의 루틴에 매개 변수 값을 전달하는 경우 드라이버는 현재 스레드 개체의 PreviousMode 필드가 KernelMode로 설정되어 있는지 확인해야 합니다.

커널 모드 드라이버는 임의 스레드의 컨텍스트에서 실행할 수 있으며 이 스레드의 PreviousMode 필드는 UserMode로 설정될 수 있습니다. 이 경우 커널 모드 드라이버는 네이티브 시스템 서비스 루틴의 Zw 버전을 호출하여 매개 변수 값이 신뢰할 수 있는 커널 모드 원본에서 온 것이라고 루틴에 알릴 수 있습니다. Zw 호출은 현재 스레드 개체의 PreviousMode 값을 재정의하는 씬 래퍼 함수로 이동합니다. 래퍼 함수는 PreviousModeKernelMode 로 설정하고 루틴의 Nt 버전을 호출합니다. 루틴의 Nt 버전에서 반환할 때 래퍼 함수는 스레드 개체의 원래 PreviousMode 값을 복원하고 를 반환합니다.

커널 모드 드라이버는 네이티브 시스템 서비스 루틴의 Nt 버전을 직접 호출할 수 있습니다. 커널 모드 드라이버가 사용자 모드 또는 커널 모드에서 발생할 수 있는 I/O 요청을 처리하는 경우 드라이버는 호출 중에 현재 스레드의 PreviousMode 값이 변경되지 않도록 루틴의 Nt 버전을 호출할 수 있습니다. NtXxx 루틴은 호출 스레드의 PreviousMode 값을 확인하여 매개 변수 값이 사용자 모드 애플리케이션 또는 커널 모드 구성 요소에서 온 것인지 여부를 확인하고 그에 따라 처리합니다.

커널 모드 드라이버가 NtXxx 루틴을 호출하고 현재 스레드 개체의 PreviousMode 값이 매개 변수 값이 사용자 모드 또는 커널 모드 원본인지 정확하게 나타내지 않는 경우 오류가 발생할 수 있습니다.

예를 들어 커널 모드 드라이버가 임의 스레드의 컨텍스트에서 실행 중이고 이 스레드의 PreviousMode 값이 UserMode로 설정되어 있다고 가정합니다. 드라이버가 커널 모드 파일 핸들을 NtClose 루틴에 전달하는 경우 이 루틴은 PreviousMode 값을 확인하고 핸들이 사용자 모드 핸들이어야 한다고 결정합니다. NtClose가 사용자 모드 핸들 테이블에서 핸들을 찾지 못하면 STATUS_INVALID_HANDLE 오류 코드가 반환됩니다. 한편, 드라이버는 커널 모드 핸들을 누수합니다. 이 핸들은 닫혀지지 않았습니다.

또 다른 예로, NtXxx 루틴의 매개 변수에 입력 또는 출력 버퍼가 포함되어 있고 PreviousMode UserMode = 인 경우 루틴은 ProbeForRead 또는 ProbeForWrite 루틴을 호출하여 버퍼의 유효성을 검사합니다. 버퍼가 사용자 모드 메모리 대신 시스템 메모리에 할당된 경우 ProbeForXxx 루틴은 예외를 발생시키고 NtXxx 루틴은 STATUS_ACCESS_VIOLATION 오류 코드를 반환합니다.

필요한 경우 드라이버는 ExGetPreviousMode 루틴을 호출하여 현재 스레드 개체에서 PreviousMode 값을 가져올 수 있습니다. 또는 드라이버는 요청된 I/O 작업을 설명하는 IRP 구조에서 RequestorMode 필드를 읽을 수 있습니다. RequestorMode 필드에는 작업을 요청한 스레드의 PreviousMode 값 복사본이 포함되어 있습니다.