태터데스크 관리자

도움말
닫기
적용하기   첫페이지 만들기

태터데스크 메시지

저장하였습니다.

Mouse Filter Driver 에 대한 정리

Posted 2008/07/25 15:44


댓글 하나가 운영자에겐 커다란 힘이 됩니다!


주의해야 할 점!!!


for( i = 0; i <= IRP_MJ_MAXIMUM_FUNCTION; i++ )
 {
        pDriverOBJ->MajorFunction[i] = FilterDispatch;
 }


요렇게 모든 루틴을 등록해 놔야 한다는 것!

해당 루틴에서는 하단에 있는 FDO 및 FiDO가 정상적으로 작동할 수 있게끔

모든 IRP를 Skip 해서 내려 보내 줘야 하는 의무가 있다.


그런데... 특이하게도

IRP_MJ_POWER 같은 경우는 IoCallDriver를 사용하지 않는다.


PoStartNextPowerIrp( pIrp ); // 다음 번 Power 관련 IRP를 받을 수 있는 상태라는 걸 표시!
IoSkipCurrentIrpStackLocation( pIrp );
ReturnStatus = PoCallDriver( pDeviceExtension->pTopLevelOBJ, pIrp ); // Power IRP를 하단에 내려보낸다.

위와 같은 루틴이 필요하게 된다.


따라서

pDriverOBJ->MajorFunction[ IRP_MJ_POWER ]   = FilterPowerRoutine;

이렇게 파워 루틴은 따로 등록을 해 주던가 해야지...


=========================================================================================================


Device Object가 2개 필요하다.

하나는 순전히 IO Manager가 보내주는 IRP를 받아서 필터를 거쳐 밑으로 내려보내기 위한 Device Object.

다른 하나는 필터를 사용하고자 하는 APP와의 통신을 위한 Device Object.


APP와의 통신을 위해서는 심볼릭 링크를 통해서 이름을 만들어 줘야 한다.

그래야 CreateFile로 접속을 할 수 있겠지.


IO Manager의 IRP를 받는 DO는 심볼릭 링크가 굳이 필요 없고

APP와의 통신을 위한 DO는 반드시 심볼릭 링크가 필요하다.


여기서 주의 할 점!

IO Manager의 IRP를 받는 Device Object를 만들 때는

기존에 있던 하위 Device Object의 Flag를 그대로 따라야 한다.


pFilterDeviceOBJ->Flags |= (pDeviceExtension->pTopLevelOBJ->Flags & ( DO_BUFFERED_IO | DO_DIRECT_IO | DO_POWER_PAGABLE ) );
pFilterDeviceOBJ->Flags &= ~DO_DEVICE_INITIALIZING;

pFilterDeviceOBJ->Characteristics = pDeviceExtension->pTopLevelOBJ->Characteristics;
pFilterDeviceOBJ->DeviceType  = pDeviceExtension->pTopLevelOBJ->DeviceType;


위와 같은 과정이 꼭 필요하다!


하지만 APP와의 통신을 위한 DO는

APP와 어떻게 데이터를 주고 받을 것인지 만 표시해 주면 된다.


pDeviceOBJForApp->Flags &= ~DO_DEVICE_INITIALIZING;
pDeviceOBJForApp->Flags |= DO_BUFFERED_IO;


여기서 DO_DEVICE_INITIALIZING 부분을 해 주지 않으면.. APP에서 CreatFile을 해도 접근 할 수가 없다.

이유는.... 글쎄다... DO_DEVICE_INITIALIZING를 Flags 에서 빼지 않으면 스택을 쌓을 수 없다고 하는데

CreateFile 할 때도 스택이 쌓이는 건지.. 잘 모르겠음.


=========================================================================================================


그렇다면..

각각의 DO 언제 생성할 것인가?


잘 생각해 보면 해답이 보인다.

심볼릭 링크를 사용하는 DO는 드라이버가 메모리에 올라가는 시점에 단 한 번만 호출되야 한다.

이유는... 같은 이름을 사용하는 심볼은 중복으로 만들어 질 수 없기 때문!

그렇다면 드라이버에서 단 한 번만 호출되는 곳은??? 바로 DeviceEntry!


IO Manager에서 IRP를 받아야 하는 DO는 장치 별로 구분이 되야 하기에

당연히 AddDevice 에서 만들어 져야 한다.


그러니까..

WDM은 하나의 드라이버가 같은 종류의 장치 여러개를 관리할 수 있으므로

만약 PC에 같은 장치가 2개 이상 꽂히게 되면

APP와 연결되는 DO는 하나만 생성되고

IO Manager에서 IRP를 받는 DO는 장치 갯수만큼 만들어진다는 것이다!


==================================================================================================================


그렇다면...

예를 들어 2개의 마우스가 설치되어 있는 상황을 가정해 보자!

내가 APP 에서 Mouse Filter Driver에 접근해서 1번 마우스를 사용하지 못하게 해라! 라는 명령을

내보내면 2개의 DO가 만들어져 있을 텐데... 어떤 DO의 사용을 막을 것인가?

뭐가 1번 마우스를 관리하는 DO인지 어떻게 구분할 것이며

만약 순서대로 만들어 지는 거 아닌가?? 라고 생각할 경우 1번 마우스를 PC에서 뺐다가 다시 꽂으면

그땐 어떤 순서로 만들어 지는지 어떻게 확신할 수 있나? 만약 마우스가 100개라면... 어떻게??


물론 위의 경우는 Class Filter Driver를 만들었을 때의 이야기다!

Class Filter는 스택의 최상위에 올라가기 때문에 개개의 장치를 구분할 수가 없다.


위의 상황을 해결 해 줄 수 있는 방법은

Device Filter Driver (장치 필터)를 만드는 것이다!


사용자 삽입 이미지

 

==================================================================================================================


계속... 그렇다면

이렇게 만든 DO를 언제 해제 시켜줄 것인가?

만드는 시점은 틀렸지만 해제 시점은 비슷하다.


즉 IRP_MN_REMOVE_DEVICE 때 다 해제 시켜줘야

DriverUnload 루틴이 호출 될 수 있다.


===================================================================================================================


자... 이제 아무 일도 안 하는 필터가 완성되었다.

뭔가 일을 해야 할 때가 온 거지요..


APP가 접근을 해야 한다.

어플리케이션이 CreateFile을 하게 되면 IRP_MJ_CREATE가 넘어오게 되는데

이건 당연히 IoCallDriver 해 주면 안 된다.

해당 루틴에서 IoCompleteRequest로 끝내야 한다.


이렇게 그 자리에서 끝내야만 하는 IRP로는

IRP_MJ_CREATE

IRP_MJ_READ

IRP_MJ_WRITE

IRP_MJ_CLOSE

IRP_MJ_CLEANUP  ----> 주의 할 것!

IRP_MJ_DEVICE_CONTROL   가 있다.


물론.. 이들 IRP를 APP와 통신하는 DO만 받을 수 있는 건 아니다.

스택의 하단에 있는 DO들도 나름대로 무언가와 통신을 하고 있기 때문에

그들을 구분해 줘야 한다.


===================================================================================================================


자.. 마우스 필터 드라이버를 만들었는데

마우스가 어떤 짓거리를 하는지 감시해야 겠지.


IO Manager가 계속 IRP_MJ_READ를 보내서 마우스에게 현재 데이터를 요청한다.

우린 그걸 감시하면 되는 거다.


해서..

Read 부분에 Complete Routine을 등록하고

그곳에서 마우스가 보내주는 데이터의 구조체를 파싱해서 감시하면 된다.

데이터를 바꿔치기 할 수 도 있고

데이터가 아예 안 온 것 처럼 속일 수도 있다.


====================================================================================================================


APP와 통신을 한 다는 이야기는 뭔가를 주고 받는다는 건데..

APP가 DeviceIoControl을 사용해 데이터를 주고 받을 수는 있지만

필터 드라이버가 감지하는 어떤 특정 시점을 APP에게 알려주기 위해서는 뭔가 다른 방법이 필요하다.


바로 Event를 공유하는 것!

APP에서 Event를 만들고 그 주소를 IoControl을 사용해서 드라이버에게 넘겨주고

드라이버에서는 그 이벤트를 커널에서 사용할 수 있도록 바꾼다음에

특정 시점에 시그널을 해 줘서 APP에게 알려주는 것이다.


물론 APP는 시그널을 감지하기 위해서 Thread를 돌려야 겠지!



[출처] Mouse Filter Driver 에 대한 정리!!!! | 작성자 조성훈

위의 정보가 도움이 되셨나요? 그렇다면 댓글 하나만 남겨주세요.
댓글 하나가 운영자에겐 커다란 힘이 됩니다!

Write your message and submit
« PREV : 1 : ... 231 : 232 : 233 : 234 : 235 : 236 : 237 : 238 : 239 : ... 436 : NEXT »