윈도우 API(간단히 WinAPI)는 사용자 모드에서 윈도우가 제공하는 기능들을 활용할 수 있도록 하는 어플리케이션 프로그래밍 인터페이스(application programming interface; API)이다. 개발자는 마이크로소프트 공식 문서를 참고하여 윈도우가 제공하는 리소스를 적극적으로 활용할 수 있다. WinAPI는 C 프로그래밍 언어로 작성되었으나 타 프로그래밍 언어를 통해서도 사용이 가능하다.
아직 16비트 시스템이 대중화된 시기에 32비트 윈도우 운영체제를 지원하는 API라는 것을 명시하기 위해 Win32라고 불렀다. 그러나 64비트의 x64 및 ARM64도 지원하면서 특정 아키텍처에 종속되지 않는 명칭으로 변경되었다.
시스템 서비스(system services)는 윈도우 커널에서 제공하는 기능을 사용자 모드에서 호출하는 일련의 절차를 가리킨다. 사용자 모드 프로세스는 보호 링 구조에 의해 커널 함수, 일명 루틴(routine)을 직접 접근할 수 없으므로 Ntdll.dll
에 내포된 진입점을 통해 Ntoskrnl.exe
커널 이미지에 정의된 루틴을 호출하게 된다.
다음은 윈도우 API 중에서 CreateFileW
함수를 호출할 때의 시스템 서비스가 진행되는 과정을 순서대로 나열한다.
CreateFileW
함수의 시스템 서비스 호출 과정순서 | 바이너리 | 이름 | 함수 | 설명 |
---|---|---|---|---|
1 | Kernel32.dll | 환경 서브시스템 DLL | KERNEL32!CreateFileW | 시스템 서비스를 호출하는 WinAPI 함수; 그 외에 User32.dll , Gdi32.dll 등이 해당 |
2 | Ntdll.dll | Native API 라이브러리 | ntdll!NtCreateFile | WinAPI로부터 요청한 사용자 모드의 루틴 진입점 |
3 | Ntoskrnl.exe | Executive | nt!NtCreateFile | WinAPI로부터 요청한 커널 모드의 루틴 |
시스템 서비스를 호출한 스레드는 syscall 명령에 의해 사용자 모드에서 커널 모드로 전환되어, 제약에 걸렸던 모든 프로세서 명령어들을 활용할 수 있게 된다. 그리고 커널 모드에서 작업이 완료되면 다시 사용자 모드로 돌아가는 원리로 동작한다.
출처: Using Nt and Zw Versions of the Native System Services Routines - Windows drivers | Microsoft Learn
위의 예시에서 NtCreateFile
을 소개하였으나, 그 외에도 ZwCreateFile
이란 시스템 서비스 API도 존재한다. Nt
는 "네이티브(native)" 용어에서 유래되었으나, Zw
는 다른 API 함수명과 혼돈을 방지하기 위해 선택된 알파벳 조합이다. 두 버전은 유사한 (혹은 동일한) 작업을 수행하며, 둘 다 사용자 및 커널 모드에서 호출할 수 있다. 차이점은 커널 모드에서 매개변수로 전달된 인자의 유효성 검증 여부이다.
참조: The Component Object Model - Win32 apps | Microsoft Learn
컴포넌트 오브젝트 모델(Component Object Model; COM)은 마이크로소프트가 1993년에 프로세스 간 통신에 호환성을 보장하기 위해 표준화한 어플리케이션 "이진" 인터페이스이다. 본 내용을 진행하기 전에 API와 ABI의 차이점을 간단히 소개할 필요가 있다.
비교 | API | ABI |
---|---|---|
라이브러리 연관성 | 함수는 무엇이 존재하며 인자의 개수와 순서가 어떤지 선언 | 함수는 어떻게 접근되며 인자는 어떻게 전달이 되는지 정의 |
인터페이스 영역 | 소스 코드 | 머신 코드 |
하드웨어 독립 | ⭕ | ❌ |
라이브러리에 정의된 데이터와 함수를 소스 코드로 불러올 때는 API가 활용되나, 이를 컴파일 된 이진 파일에서 접근 및 호출할 때에는 ABI가 활용된다. 이는 개발에 사용된 프로그래밍 언어와 컴파일러 상관없이, 서로 달리 제작된 어플리케이션이나 라이브러리 사이에서도 상호작용을 가능케 만든다. 단, COM 제작 및 사용을 할 수 있는 프로그래밍 언어로써는 가상 메소드 테이블을 활용할 수 있는 포인터가 지원되어야 한다.
C# 프로그래밍 언어의 인터페이스 및 클래스에 대한 지식은 개념의 유사성으로 COM을 이해하는데 도움이 된다: COM 클래스는 도입된 COM 인터페이스의 텅 빈 가상 메소드에 실질적인 함수 코드(일명 컴포넌트, 혹은 COM 오브젝트)를 정의하는데, 해당 컴포넌트를 사용하기 위해서는 오로지 COM 인터페이스로만 접근될 수 있다. 그리고 COM 오브젝트 호출하는 자를 COM 클라이언트, 그리고 제공하는 자를 COM 서버라고 지칭한다.