마크 루시노비치 출판: 2006년 11월 1일
Introduction
NT의 아키텍처에 대해 잘 알고 있다면 Win32 애플리케이션에서 사용하는 API가 "실제" NT API가 아니라는 것을 알고 있을 것입니다. POSIX, OS/2 및 Win32를 포함하는 NT의 운영 환경은 자체 API를 통해 클라이언트 애플리케이션과 통신하지만 NT "네이티브" API를 사용하여 NT와 통신합니다. 네이티브 API는 대부분 문서화되지 않았으며, Windows NT 디바이스 드라이버 키트에 설명된 250개의 함수 중 약 25개에 불과합니다.
그러나 대부분의 사람들이 모르는 것은 운영 환경의 클라이언트가 아닌 NT에 "네이티브" 애플리케이션이 존재한다는 것입니다. 이러한 프로그램은 네이티브 NT API를 사용하며 Win32와 같은 운영 환경 API를 사용할 수 없습니다. 이러한 프로그램이 필요한 이유" Win32 하위 시스템이 시작되기 전에 실행해야 하는 모든 프로그램(로그온 상자가 나타날 무렵)은 네이티브 애플리케이션이어야 합니다. 네이티브 애플리케이션의 가장 눈에 띄는 예는 초기화 시 표시되는 블루 스크린에서 chkdsk를 실행하는 "autochk" 프로그램입니다(화면에 '.'들을 표시하는 프로그램입니다). 당연히 Win32 운영 환경 서버인 CSRSS.EXE(Client-Server 런타임 하위 시스템)도 네이티브 애플리케이션이어야 합니다.
이 문서에서는 네이티브 애플리케이션을 빌드하는 방법과 작동 방식을 설명합니다.
Autochk 실행 방법
Autochk 는 NT의 부팅 및 시스템 시작 드라이버가 로드되는 시간과 페이징이 켜져 있는 시간 사이에 실행됩니다. 이 시점에서 부팅 시퀀스 세션 관리자(smss.exe)는 NT의 사용자 모드 환경을 오프 더 그라운드로 가져오고 다른 프로그램은 활성 상태가 아닙니다. HKLM\System\CurrentControlSet\Control\Session Manager\BootExecute 값인 MULTI_SZ 세션 관리자에서 실행되는 프로그램의 이름과 인수를 포함하며 Autochk가 지정된 위치입니다. 이 값을 살펴보면 일반적으로 다음과 같은 내용이 나타납니다. 이때 "Autochk"에는 "*"가 인수로 전달됩니다.
Autocheck Autochk *
세션 관리자는 winnt<\system32 디렉터리에서 >이 값에 나열된 실행 파일을 찾습니다. Autochk가 실행되면 파일이 열리지 않으므로 Autochk 는 부팅 드라이브를 포함하여 원시 모드에서 볼륨을 열고 디스크 내 데이터 구조를 조작할 수 있습니다. 이것은 나중에 가능하지 않을 것입니다.
네이티브 애플리케이션 빌드
Microsoft 문서화하지 않지만 NT DDK 빌드 유틸리티는 네이티브 애플리케이션을 만드는 방법을 알고 있으며 Autochk를 컴파일하는 데 사용될 수 있습니다. 디바이스 드라이버에 대해 수행되는 것과 동일하게 애플리케이션을 정의하는 SOURCES 파일에 정보를 지정합니다. 그러나 빌드에 드라이버를 원하는 것으로 나타내는 대신 다음과 같이 원본 파일에서 네이티브 애플리케이션을 사용하라고 알릴 수 있습니다.
TARGETTYPE=PROGRAM
Build 유틸리티는 표준 메이크파일인 \ddk\inc\makefile.def를 지침으로 사용하며, 이 메이크파일은 네이티브 애플리케이션을 컴파일할 때 nt.lib라는 런타임 라이브러리를 찾습니다. 아쉽게도 Microsoft DDK(Server 2003 DDK에 포함된 파일)와 함께 이 파일을 배송하지 않지만, 해당 버전과 연결하면 네이티브 애플리케이션이 XP 또는 Windows 2000에서 실행되지 않을 것으로 의심됩니다. 그러나 visual C++의 런타임 라이브러리인 msvcrt.lib를 지정하여 nt.lib 선택을 재정의하는 makefile.def에 줄을 포함하여 이 문제를 해결할 수 있습니다.
DDK의 "확인된 빌드" 환경에서 빌드 를 실행하면 %BASEDIR%\lib%CPU%\Checked(예: c:\ddk\lib\i386\checked\native.exe)에서 전체 디버그 정보가 포함된 네이티브 애플리케이션이 생성되고, "무료 빌드" 환경에서 빌드를 호출하면 프로그램의 릴리스 버전이 %BASEDIR%\lib%CPU%\Free로 종료됩니다. 이러한 위치는 빌드에서 디바이스 드라이버 이미지를 배치하는 위치와 동일합니다.
네이티브 애플리케이션에는 ".exe" 파일 확장명이 있지만 Win32 .exe같은 확장명은 실행할 수 없습니다. 시도하면 메시지가 표시됩니다.
애플리케이션은 Windows NT 모드에서 실행할 수 없습니다.
네이티브 애플리케이션 내부
winmain 또는 main 대신 네이티브 애플리케이션의 진입점은 NtProcessStartup입니다. 또한 다른 Win32 진입점과 달리 네이티브 애플리케이션은 명령줄 인수를 찾기 위해 유일한 매개 변수로 전달된 데이터 구조에 도달해야 합니다.
네이티브 애플리케이션의 런타임 환경 대부분은 NT의 네이티브 API 내보내기 라이브러리인 NTDLL.DLL 의해 제공됩니다. 네이티브 애플리케이션은 NTDLL 함수인 RtlCreateHeap을 사용하여 스토리지를 할당할 자체 힙을 만들어야 합니다. 메모리는 RtlAllocateHeap 을 사용하여 힙에서 할당되고 RtlFreeHeap을 사용하여 해제됩니다. 네이티브 애플리케이션이 화면에 무언가를 인쇄하려는 경우 NtDisplayString 함수를 사용해야 합니다. 이 함수는 초기화 블루 스크린으로 출력됩니다.
반환할 런타임 코드가 없으므로 네이티브 애플리케이션은 Win32 프로그램과 같은 시작 함수에서 단순히 반환되지 않습니다. 대신 NtProcessTerminate를 호출하여 자신을 종료해야 합니다.
NTDLL 런타임은 네이티브 애플리케이션이 파일 I/O를 수행하고, 디바이스 드라이버와 상호 작용하고, 프로세스 간 통신을 수행할 수 있도록 하는 수백 개의 함수로 구성됩니다. 불행히도, 앞서 언급했듯이, 이러한 기능의 대부분은 문서화되지 않았습니다.