다음을 통해 공유


내보내기 드라이버 만들기

내보내기 드라이버는 다양한 다른 하드웨어별 또는 디바이스 스택별 구성 요소에서 로드할 수 있는 커널 모드 DLL이지만 전체 커널 모드 드라이버의 특징은 일부 없습니다. 특히 내보내기 드라이버에는 디스패치 테이블이 없으며 드라이버 스택에 위치가 없으며 서비스 제어 관리자의 데이터베이스에 시스템 서비스로 정의하는 항목이 없습니다. 내보내기 드라이버에는 디스패치 테이블이 없지만 표준 드라이버에 디스패치 루틴을 제공할 수 있습니다. 표준 드라이버는 자체 디스패치 테이블에 디스패치 루틴을 삽입합니다. 내보내기 드라이버에는 호출되지 않는 스텁 DriverEntry 루틴이 있습니다.

커널 모드 내보내기 드라이버는 기본 스택 및 하드웨어 특성과 독립적인 드라이버 쌍의 일부를 구현하는 데 특히 적합합니다.

Windows에는 다른 드라이버에 의해 로드되는 여러 내보내기 드라이버가 포함되어 있습니다. 예를 들면 다음과 같습니다.

  • SCSI 포트 드라이버
  • 테이프 클래스 드라이버
  • IDE 컨트롤러 드라이버는 모두 시스템에서 제공하는 내보내기 드라이버입니다.

표준 드라이버는 내보내기 드라이버로도 작동할 수 있습니다. 드라이버가 두 가지 방법으로 작동하려면 내보내기 드라이버로 빌드하고 일반 드라이버로 로드해야 합니다.

내보내기 드라이버 빌드

Visual Studio에서 내보내기 드라이버를 만들려면 다음 절차를 사용합니다.

  1. 빈 WDM 드라이버와 같은 템플릿에서 새 프로젝트를 만듭니다.
  2. 프로젝트에 모듈 정의 파일을 추가합니다. 예를 들면 다음과 같습니다.
LIBRARY mydriver.sys
EXPORTS
  DllInitialize PRIVATE
  DllUnload PRIVATE

커널 모드 DLL의 진입점은 항상 DllInitialize입니다. 시스템은 DLL이 로드된 직후 커널 모드 DLL의 DllInitialize 루틴을 호출합니다. 내보내기 드라이버는 DllInitialize 루틴을 제공해야 합니다. DllInitialize 루틴을 사용하여 DLL의 다른 루틴에 필요한 리소스를 가져오거나 초기화할 수 있습니다.

DLLENTRY 매크로를 사용하여 진입점을 지정할 수 없습니다.

NTSTATUS DllInitialize(
  _In_ PUNICODE_STRING RegistryPath
);

RegistryPath는 DLL 레지스트리 키의 경로를 지정하는 계산된 유니코드 문자열에 대한 포인터로, HKEY_LOCAL_MACHINE\CurrentControlSet\Services\DllName. DLL 루틴은 이 키를 사용하여 DLL 관련 정보를 저장할 수 있습니다. DllInitialize가 종료되면 RegistryPath에서 가리키는 버퍼가 해제됩니다. 따라서 DLL이 키를 사용하는 경우 DllInitialize 는 키 이름을 복제해야 합니다.

빌드 프로세스는 .lib 확장이 있는 내보내기 라이브러리와 .sys 확장이 있는 내보내기 드라이버를 생성합니다.

내보내기 드라이버에서 함수 가져오기

내보내기 드라이버에서 내보낸 함수를 가져오려면 Ntdef.h에 정의된 DECLSPEC_IMPORT 매크로를 사용하여 함수를 선언해야 합니다. 예를 들면 다음과 같습니다.

DECLSPEC_IMPORT int LoadPrinterDriver (int arg1); 

이 매크로는 필요한 경우 해당 플랫폼에서 __declspec(dllimport) 스토리지 클래스 선언으로 확인되고 필요하지 않은 플랫폼에서는 아무 것도 확인하지 않습니다.

내보내기 드라이버에서 내보낼 함수는 DECLSPEC_EXPORT 매크로를 사용하여 선언해야 합니다. 이 매크로는 필요한 경우 해당 플랫폼에서 __declspec(dllexport) 스토리지 클래스 선언으로 확인되고 필요하지 않은 플랫폼에는 아무 것도 없습니다. 내보내기 드라이버가 표준 드라이버에 디스패치 루틴을 제공하는 경우 해당 루틴을 내보낼 필요가 없습니다.

내보내기 드라이버 로드 및 언로드

내보내기 드라이버는 %Windir%\System32\Drivers 디렉터리에 설치해야 합니다. Windows 2000부터 운영 체제는 내보내기 드라이버의 함수를 다른 드라이버에서 가져온 횟수를 나타내는 참조 횟수를 유지합니다. 시스템은 가져오는 드라이버 중 하나가 언로드할 때마다 이 수를 감소합니다. 참조 수가 0으로 떨어지면 시스템은 내보내기 드라이버를 언로드합니다. 그러나 내보내기 드라이버에는 표준 진입점 및 언로드 루틴, DllInitializeDllUnload가 포함되어야 합니다. 그렇지 않으면 운영 체제에서 이 참조 개수 메커니즘을 활성화하지 않습니다.

시스템은 DLL을 언로드할 때 커널 모드 DLL의 DllUnload 루틴을 호출합니다.

NTSTATUS DllUnload(void);

내보내기 드라이버는 DllUnload 루틴을 제공해야 합니다. DllUnload 루틴을 사용하여 DLL의 루틴에서 사용하는 모든 리소스를 해제할 수 있습니다.