Windows XP에서부터 내가 생성하는 exe 바이너리의 내부에 xml 문서 리소스 형태의 메타데이터를 집어넣는 게 필수 관행이 됐다.
가장 대표적인 용도는 (1) 내가 사용하는 시스템 DLL의 버전을 지정해서 로딩 방식을 시스템 디렉터리 말고 딴 곳으로 강제로 바꾸는 것이다.
이 방식으로 (1-1) 공용 컨트롤을 6.0 버전을 사용한다고 명시해야 각종 컨트롤에 XP의 새끈한 테마가 적용되어 나왔다. 테마 기능을 추가하는 과정에서 comctl32.dll이 XP 이전과 XP 이후 것은 하위 호환성이 없이 서로 단절됐기 때문이라 한다.
내 프로그램의 비주얼이 시대에 뒤떨어진 구닥다리처럼 보이지 않게 하려면 이거 지정은 선택의 여지가 없는 필수이다.
XP 이후로 지금까지 comctl32.dll이 7.0으로 올라간다든가 해서 또 breaking changing을 겪지는 않았다.
Windows 8부터는 명목상 고전 테마와 표준 테마의 구분이 없어지긴 했지만, 그래도 공용 컨트롤 6.0 지정을 안 해도 되는 건 아니다. 구닥다리 비주얼 자체가 호환성 때문에 완전히 없어진 건 아니기 때문이다.
뭐 comctl32가 가장 대표적이긴 하지만 이 외에 (1-2) GDI+ (gdiplus.dll)와 비주얼 C++의 CRT DLL, 그리고 MFC DLL이 지난 200x년도에 이 방식을 사용해 로딩된 적이 있다.
Windows XP 시절엔 WinSxS 디렉터리에 파일이 몇 개 없었지만 Vista 이후부터는 도대체 뭐가 들어갔는지 여기에 디렉터리 수가 무려 수천~만수천 개에 달할 정도로 많아졌다. 199x년대에 한번 DLL hell을 겪은 뒤, 너무 난장판이 돼 가는 시스템 디렉터리를 이런 식으로 정리를 하려 했던 모양이다. 같은 DLL이라도 버전별로 쫙 따로 분류를...
하지만 DLL을 배포하기가 너무 불편하다는 원성이 빗발치면서 VC++ 201x부터는 CRT와 MFC DLL 로딩 방식이 다시 재래식 시스템 디렉터리 기반으로 복귀했다.
또한 GDI+도 오늘날은 기존 GDI만큼이나 재래식 유물로 전락했고... 요즘은 딱히 이 WinSxS 기반 DLL 로딩이 활발히 쓰이고 있는지 모르겠다.
DLL 버전 설명이 좀 길어졌는데, 이것 말고도 xml에 들어가는 정보로는
(2) 내 프로그램이 고해상도+가변 DPI를 인식한다는 플래그
(3) 반드시 관리자 권한이 필요하다는 식의 권한 플래그
가 Vista에서 추가되었다. 시스템 차원에서의 고해상도 DPI 설정이야 더 말할 것도 없고 Windows 8.1부터는(8도 아님) 실행 중에 on-the-fly로 모니터 단위 DPI 설정이 변경되는 것에도 추가로 대비가 돼 있어야 한다. 그런 표식이 없으면 그냥 그래픽 카드의 힘으로 프로그램 화면이 그대로 기계적으로 확대 축소된다.
먼 옛날, Windows NT 3.x 내지 95 시절엔 화면 해상도를 재부팅 없이 on-the-fly로 바꾸는 것만 해도 굉장한 혁신이었는데 참 격세지감이다. 시스템 DPI도 예전에는 재부팅이 필수였지만 그래도 Windows Vista쯤부터는 그냥 재로그인만 하면 되게 규제가 완화됐다.
그리고 Vista부터인지 7부터인지는 모르겠지만 (4) 이 프로그램이 인식하는 운영체제 목록도 xml에다 명시하게 되었다. PE 실행 파일 포맷에 명시된 OS 버전의 역할을 어느 정도 대신하게 됐다.
Windows 8.1부터는 GetVersionEx가 알 수 없는 이유로 인해 봉인되어서, 프로그램이 인식하는 걸로 등록되지 않은 최신 운영체제의 버전은 Windows 8 이상으로는 알려주지 않게 바뀌었다. 도대체 이런 만행을 왜 무슨 이유 때문에 저질렀는지 난 모르겠지만.. 도대체 버전을 숨겨서 뭐 하게?
그리고 Windows 7도.. 자기 버전이 명시되지 않은 EXE 프로그램이 이름이 setup이라거나 하면, 실행 후에 "이 프로그램은 혹시 설치 프로그램인가요? 뭔가가 제대로 설치/제거되지 않았을 수 있습니다" 이런 꼬장을 부린다. 무슨 호환성과 관련된 조치인 듯하다.
결국 처음에는 공용 컨트롤 때문에 사용하기 시작한 xml인데 이제는 무슨 실행 프로그램을 제대로 만들려면 메타데이터 xml을 집어넣는 건 거의 필수가 되었다. 이 프로그램이 미래에 운영체제에서 새로 도입되는 시스템이나 기능을 받아들일 준비가 됐다는 것을 나타내는 증서 역할을 하다 보니, 들어가는 내용이 점점 증가하고 있다. 저 네 가지 아이템 말고 내가 또 빠뜨린 게 있는지 모르겠다.
그리고, PE 헤더에 운영체제 버전과 서브시스템 버전은 왜 따로 존재하고 둘의 차이가 무엇인지도 본인은 궁금하다.
* 추가 설명
사실, 메모장이나 워드패드처럼 Windows에 포함되어 있는 기본 프로그램들은 내부의 매니페스트 XML을 열어 보면 공용 컨트롤, 고해상도 DPI, 실행 권한 같은 설정은 있지만 굳이 운영체제 정보가 들어있지는 않다. 특정 버전의 운영체제에 포함되어 있는 프로그램들이 또 그 운영체제 GUID가 내장되어 있다거나 하지는 않다.
이때는 PE 헤더 차원에서 명시된 운영체제 버전이 활용된다. 이 버전이 Windows 8.1에 달할 정도로 높은 값이 들어있으면 GetVersionEx 함수도 Windows 8.1의 버전도 정확하게 되돌려 준다. 다만 이 경우, 그 실행 파일은 Windows 8.1 미만의 운영체제에서는 전혀 실행되지 않는다는 것을 감안해야 한다. 심지어 7에서도 실행이 거부된다.
Posted by 사무엘