성태의 닷넷 이야기
홈 주인
모아 놓은 자료
프로그래밍
질문/답변
사용자 관리
사용자
메뉴
아티클
외부 아티클
유용한 코드
온라인 기능
MathJax 입력기
최근 덧글
[정성태] VT sequences to "CONOUT$" vs. STD_O...
[정성태] NetCoreDbg is a managed code debugg...
[정성태] Evaluating tail call elimination in...
[정성태] What’s new in System.Text.Json in ....
[정성태] What's new in .NET 9: Cryptography ...
[정성태] 아... 제시해 주신 "https://akrzemi1.wordp...
[정성태] 다시 질문을 정리할 필요가 있을 것 같습니다. 제가 본문에...
[이승준] 완전히 잘못 짚었습니다. 댓글 지우고 싶네요. 검색을 해보...
[정성태] 우선 답글 감사합니다. ^^ 그런데, 사실 저 예제는 (g...
[이승준] 수정이 안되어서... byteArray는 BYTE* 타입입니다...
글쓰기
제목
이름
암호
전자우편
HTML
홈페이지
유형
제니퍼 .NET
닷넷
COM 개체 관련
스크립트
VC++
VS.NET IDE
Windows
Team Foundation Server
디버깅 기술
오류 유형
개발 환경 구성
웹
기타
Linux
Java
DDK
Math
Phone
Graphics
사물인터넷
부모글 보이기/감추기
내용
<div style='display: inline'> <div style='font-family: 맑은 고딕, Consolas; font-size: 20pt; color: #006699; text-align: center; font-weight: bold'>Device Driver 응용 프로그램의 빌드 스크립트 - 두 번째 이야기</div> <br /> 예전에, Device Driver 응용 프로그램을 빌드하는 것에 대한 글을 썼는데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Device Driver 응용 프로그램의 빌드 스크립트 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/921'>http://www.sysnet.pe.kr/2/0/921</a> </pre> <br /> 역시, 초보이다 보니 ^^ 현실에 안 맞는 부분이 몇 개 있어서 수정합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 우선, 그 예제 솔루션에 있던 ntifs.h 파일은 삭제합니다. 왜냐하면 "<a target='_tab' href='http://www.acc.umu.se/~bosse/ntifs.h'>http://www.acc.umu.se/~bosse/ntifs.h</a>" 사이트에서 구한 것인데, XP/2003 버전까지만 되어 있고, Windows Vista 급 이상부터는 전혀 업데이트가 안되어 있기 때문에 사용할 만한 가치가 없어보였습니다. 어차피 지원은 Windows 7까지를 고려해야 하는데, 차라리 WDK에서 제공되는 ntifs.h 파일이 더욱 현실적이기 때문입니다.<br /> <br /> 따라서, 예제에 있던 다음의 코드는 Offset 값으로 치환되어야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > { PEPROCESS pEprocess = PsGetCurrentProcess(); char subsystemVersion[1024]; StringCchPrintfA(subsystemVersion, 1024, "Subsystem Version: %d.%d\n", <b style='COLOR: blue'>pEprocess->SubSystemMajorVersion, pEprocess->SubSystemMinorVersion);</b> DbgPrint(subsystemVersion); } </pre> <br /> 자, 옵셋값으로 치환되려면 이제 운영체제에 대한 고려를 해야 합니다. 이전에 설명한 글에서는 이를 지정하기 위해서 별도의 PLATFORM_PREPROCESSOR 전처리기를 연결하려고 애썼는데 이럴 필요가 없습니다. WDK 내부의 헤더파일들은 모두 이미 NTDDI_VERSION라는 전처리기를 이용하고 있기 때문에 이것을 맞춰주면 되는 것이었습니다.<br /> <br /> 운영체제별로 어떤 값을 지정할 지는 WDK의 sdkddkver.h 파일에서 확인할 수 있는데요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > #define NTDDI_WIN2K 0x05000000 #define NTDDI_WIN2KSP1 0x05000100 ...[생략]... #define NTDDI_LONGHORN NTDDI_VISTA #define NTDDI_WS08 NTDDI_WIN6SP1 #define NTDDI_WS08SP2 NTDDI_WIN6SP2 #define NTDDI_WS08SP3 NTDDI_WIN6SP3 #define NTDDI_WS08SP4 NTDDI_WIN6SP4 #define NTDDI_WIN7 0x06010000 </pre> <br /> 아하, 그렇다면 빌드 스크립트에 다음과 같이 지정해 주면 되겠군요.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" <b style='COLOR: blue'>/p:PLATFORM_PREPROCESSOR="NTDDI_VERSION=0x05020000"</b> /p:Platform=Win32;Configuration=%BUILDCONFIG% /p:TargetName=%SERVICENAME32% /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\ </pre> <br /> 한 가지 더 정의해 주어야 합니다. NTDDI_VERSION와 함께 _WIN32_WINNT도 지정해 주어야 하는데 역시 다음과 같이 이미 정의되어 있는 값들을 적절하게 사용해 주어야 합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > #define _WIN32_WINNT_NT4 0x0400 #define _WIN32_WINNT_WIN2K 0x0500 #define _WIN32_WINNT_WINXP 0x0501 #define _WIN32_WINNT_WS03 0x0502 #define _WIN32_WINNT_WIN6 0x0600 #define _WIN32_WINNT_VISTA 0x0600 #define _WIN32_WINNT_WS08 0x0600 #define _WIN32_WINNT_LONGHORN 0x0600 #define _WIN32_WINNT_WIN7 0x0601 </pre> <br /> 그래서, msbuild 실행 시 전처리기 정의는 다음과 같이 운영체제마다 달리 해주시면 됩니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > msbuild "...\DeviceDriverSample.vcxproj" <b style='COLOR: blue'>/p:PLATFORM_PREPROCESSOR="NTDDI_VERSION=0x05020000;_WIN32_WINNT=0x0502"</b> /p:Platform=Win32;Configuration=%BUILDCONFIG% /p:TargetName=%SERVICENAME32% /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\ </pre> <br /> 이제 소스 코드에서 예제로 사용된 SubSystemMajorVersion과 SubSystemMinorVersion 필드는 옵셋 값으로 정의해 주는 것만 남았는데요. 예제를 간략히 하기 위해 ImageFileName으로 대신하겠습니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > #if <b style='COLOR: blue'>NTDDI_VERSION == NTDDI_WS03</b> #if defined(<b style='COLOR: blue'>_AMD64_</b>) #define PSOFFSET_IMAGEFILENAME 0x268 // windows 2003 x64 #else #define PSOFFSET_IMAGEFILENAME 0x164 // windows 2003 x86 #endif #elif <b style='COLOR: blue'>NTDDI_VERSION == NTDDI_WIN7</b> #if defined(_AMD64_) #define PSOFFSET_IMAGEFILENAME 0x2e0 // windows 7 x64 #else #define PSOFFSET_IMAGEFILENAME 0x16c // windows 7 x86 #endif #endif </pre> <br /> 마지막으로 수정해야 할 것 하나 더! 이전 글에서 참고했던 DDK 빌드 설정에서는 LIB 경로를 모두 Visual Studio 프로젝트 설정 내에서 했는데요. <br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Visual Studio 2010 - Device Driver 제작- Hello World 예제 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/919'>http://www.sysnet.pe.kr/2/0/919</a> </pre> <br /> 빌드 스크립트에도 역시 이 설정을 반영해 주어야 합니다. 이를 위해서 PropertyGroup을 다음과 같은 식으로 변경해주어야 하는데,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'"> <LinkIncremental></LinkIncremental> ...[생략]... <b style='COLOR: blue'> <LibraryPath>$(DDK_LIB_PATH)</LibraryPath> </b> <ReferencePath /> </PropertyGroup> </pre> <br /> 개인적으로 이 부분이 가장 난감한 부분인데요. 만약, 모든 빌드(Win32/x64, Debug/Release)에 대해서 위와 같이 DDK_LIB_PATH를 설정해 주면 Visual Studio IDE 내에서 빌드할 때 실패해 버립니다. 왜냐하면, IDE 내에서는 $(DDK_LIB_PATH)가 정의되어 있지 않기 때문입니다. 가능한 전역 환경 변수 설정을 피하려고 했는데, 여기서만큼은 방법이 없군요. ^^ 어쩔 수 없이, 전역 환경 변수 DDK_LIB_PATH를 자신의 로컬 테스트 환경에 맞게 설정한 다음 Visual Studio를 재시작해주어야 합니다. (그래서, 제 컴퓨터에는 DDK_LIB_PATH가 "C:\WinDDK\7600.16385.1\lib\win7\amd64"로 설정되어 있습니다.)<br /> <br /> 자, 그럼 이제 다시 빌드 스크립트로 돌아와서 다음과 같이 DDK_LIB_PATH를 각 빌드마다 변경해 주는 것이 가능합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > SET DDK_LIB_PATH=C:\WinDDK\7600.16385.1\lib\wnet\i386 msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" ... /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\ SET DDK_LIB_PATH=C:\WinDDK\7600.16385.1\lib\wnet\amd64 msbuild ".\DeviceDriverSample\DeviceDriverSample.vcxproj" ... /p:OutDir=%CURRENTDIR%bin\%TARGETOS%\ </pre> <br /> 이 정도면 제법 보완이 된 것 같지요. ^^<br /> <br /> <a target='_tab' href='http://www.sysnet.pe.kr/bbs/DownloadAttachment.aspx?wid=936&boardid=331301885'>첨부한 파일은 위의 작업이 반영된 예제 솔루션</a>입니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 그 외에, 시행착오한 것을 살펴보면.<br /> <br /> DriverMain.c가 "C" 언어 구문으로 컴파일이 되어 변수 선언을 함수 초기 또는 블록 바로 다음에만 해야하는 제약이 있습니다. 특히나, DbgPrint 같은 진단 코드를 별 생각 없이 아무데나 끼워넣을 때 다음과 같은 식으로 오류가 발생합니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > NTSTATUS DriverEntry(PDRIVER_OBJECT pDriverObject, PUNICODE_STRING pRegistryPath) { DbgPrint("DriverEntry\n"); char imageFileName[100]; return STATUS_SUCCESS; } </pre> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > error C2143: syntax error : missing ';' before 'type' </pre> <br /> 순수 "C" 언어 해본지 하도 오래되어서 처음엔 왜 이런 오류가 발생하는지 몰라서 헤맸는데요. ^^;<br /> <br /> C++ 구문의 이점을 누리지 않겠다고 작정했으면, "char imageFileName[]" 선언을 함수 초기로 올려주거나, 별도의 "{", "}" 블럭으로 감싸주면 됩니다. 만약, C++ 컴파일로 바꾸겠다면? 일관성을 위해 DriverMain.c의 확장자를 DriverMain.cpp로 바꿔주고 해당 파일의 속성 창을 열어 다음과 같이 "Advanced" / "Compile As" 값을 "Compile as C++ Code (/TP)"로 바꿔주어야 합니다. (만약, 프로젝트에 파일 추가 시 확장자가 cpp였다면 자동으로 /TP 옵션으로 지정됩니다.)<br /> <br /> <img alt='how_to_build_driver_app_1.png' src='/SysWebRes/bbs/how_to_build_driver_app_1.png' /><br /> <br /> 두 번째로, windbg의 "dt" 명령어를 통해서 알아내는 구조체가 "커널 모드"냐 "사용자 모드"냐에 따라 달라지는 경우가 있다는 것!<br /> <br /> windbg의 커널 모드 진입에 대해서는 다음에서 설명드렸고,<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Windbg - Local Kernel Debug 모드 ; <a target='_tab' href='http://www.sysnet.pe.kr/2/0/934'>http://www.sysnet.pe.kr/2/0/934</a> </pre> <br /> 어떻게 달라지는지 예를 들어 보면,<br /> <br /> 다음은, 윈도우 7 x64 시스템에서 notepad.exe에 대해 "Attach to a Process..."로 "사용자 모드" 디버깅 상태에 들어갔을 때 "_EPROCESS" 구조의 일부입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > +0x2c0 FreeTebHint : Ptr64 Void +0x2c8 PageDirectoryPte : _HARDWARE_PTE +0x2c8 Filler : Uint8B +0x2d0 Session : Ptr64 Void +<b style='COLOR: blue'>0x2d8 ImageFileName</b> : [15] UChar +0x2e7 PriorityClass : UChar </pre> <br /> 아래는 "커널 모드" 디버깅 상태입니다.<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > +0x2c0 FreeTebHint : Ptr64 Void <b style='COLOR: blue'>+0x2c8 FreeUmsTebHint</b> : Ptr64 Void +0x2d0 PageDirectoryPte : _HARDWARE_PTE +0x2d0 Filler : Uint8B +0x2d8 Session : Ptr64 Void +<b style='COLOR: blue'>0x2e0 ImageFileName</b> : [15] UChar </pre> <br /> 이름은 같은 구조체인데 "사용자 모드" / "커널 모드"에 따라 달라지기 때문에 구조체 옵셋을 알아볼 때 주의하셔야 합니다.<br /> <br /> <hr style='width: 50%' /><br /> <br /> 마지막으로, 저야 뭐 재미삼아서 DDK 분야를 기웃거리고 있지만, 사용자 응용 프로그램 분야에 비해 너무나도 자료가 없다는 것이 실감납니다. 아래의 글이, 아마도 그에 대한 증명이 아닐까 싶은데요. ^^<br /> <br /> <pre style='margin: 10px 0px 10px 10px; padding: 10px 0px 10px 10px; width: 800px; background-color: #fbedbb; overflow-x: scroll; font-family: Consolas, Verdana;' > Virtual HID Mouse & Keyboard Driver (가상키보드 마우스 드라이버) ; <a target='_tab' href='http://www.hanistory.com/89631'>http://www.hanistory.com/89631</a> </pre> <br /> 정말 눈물겨운 스토리입니다. ^^; 저만 해도, 벌써 windbg에 "커널 모드"라는 것 자체가 있었는지도 몰랐으니, 가상 HID 드라이버를 만든다는 것은 그야말로 무에서 유를 창조하는 것과 다를 바가 없습니다.<br /> <br /> 사실, DDK라는 분야가 너무나 방대하고 서로 엮어져 있다는 것도 문제라면 문제겠지요. 게다가 포럼을 통해 답을 얻는 것도 마찬가지입니다. 시간이 금쪽같이 귀해진 시대에 살면서, 밑바닥 지식부터 하나하나 친절하게 설명할 수 있는 답변자를 기대하는 것은 어쩌면 욕심이라고 볼 수도 있습니다.<br /> <br /> 어쨌든... 방법이라면... 다들 차근차근히 문서화를 하자고요. ^^<br /> <br /> 결정적으로 위의 글에서 마음에 공감가는 부분을 소개하자면,<br /> <br /> <div style='BACKGROUND-COLOR: #ccffcc; padding: 10px 10px 5px 10px; width: 700px; MARGIN: 0px 10px 10px 10px; FONT-FAMILY: 맑은 고딕, Consolas, Verdana; COLOR: #005555'> 이렇게 기술문서를 공개하는 이유에는 여러가지가 있지만 무엇보다 이 기술이라는 분야는 언젠가는 자신이 알고있는 오늘의 기술이 내일의 쓰레기가 된다. 일찌감치 알고있는 정보들은 공개하고 더 높은 곳으로 계속 뛰어오를때 진정으로 아무도 가보지못한 고지에 오른 것이다. 그래야 스스로가 발전하는 길이고 바로 모두가 발전하는 길일 것이다.<br /> </div><br /> <br /> 저 역시, 제 블로그에 공개하는 정보들이 위의 취지에서와 같습니다. "오늘의 기술"이라는 것이 사실 조금만 시간이 지나도 쓰레기가 되어 버립니다. 차라리, 그것들을 공개해서 많은 사람들이 나눠쓰고 좀 더 빨리 "내일의 기술"을 앞당기는 것이 더 바람직합니다.<br /> <br /> <br /> <br /><br /><hr /><span style='color: Maroon'>[이 토픽에 대해서 여러분들과 의견을 공유하고 싶습니다. 틀리거나 미흡한 부분 또는 의문 사항이 있으시면 언제든 댓글 남겨주십시오.]</span> </div>
첨부파일
스팸 방지용 인증 번호
2730
(왼쪽의 숫자를 입력해야 합니다.)