반응형

마운트된 디스크의 드라이브 문자 구하기

 

참고로 첫번째 인자로 전달되는 VolumeDeviceObject는 마운트된 볼륨과 관련된 Filesystem DeviceObject를 대상으로 IoGetDiskDeviceObject()를 호출하여 구할 수 있다.


RtlVolumeDeviceToDosName

The RtlVolumeDeviceToDosName routine is obsolete for Windows XP and later. Use IoVolumeDeviceToDosName instead.

RtlVolumeDeviceToDosName returns the MS-DOS path for a specified device object that represents a file system volume.

NTSTATUS
  RtlVolumeDeviceToDosName(
    IN  PVOID  VolumeDeviceObject,
    OUT PUNICODE_STRING  DosName
    );

Parameters

VolumeDeviceObject
Pointer to a device object that represents a volume device object created by a storage class driver.
DosName
Pointer to a Unicode string containing the MS-DOS path of the volume device object specified by VolumeDeviceObject.

Return Value

RtlVolumeDeviceToDosName returns STATUS_SUCCESS or an appropriate error status.

Comments

The behavior of this routine is identical to that of IoVolumeDeviceToDosName. For more information about how to use this routine, see IoVolumeDeviceToDosName.

Drivers that must work on older NT-based operating systems may use this routine. Drivers written for Windows XP and later must use IoVolumeDeviceToDosName instead.

Requirements

Versions: Obsolete for Microsoft Windows XP and later. Use IoVolumeDeviceToDosName instead.

Headers: Declared in ntddk.h. Include ntddk.h.

반응형
반응형

FileSystem Devive Object Storage Device Object 얻기


MSDN에는 windows 2000 sp4 이상 지원하는 것으로 명기되어 있지만, 실제 확인해 보니 windows 2000 professional sp4에서는 지원하지 않는다.



IoGetDiskDeviceObject

The IoGetDiskDeviceObject routine retrieves a pointer to the disk device object associated with a given file system volume device object.

NTSTATUS
  IoGetDiskDeviceObject(
    IN PDEVICE_OBJECT  FileSystemDeviceObject,
    OUT PDEVICE_OBJECT  *DeviceObject
    ); 

Parameters

FileSystemDeviceObject
Pointer to the file system device object.
DeviceObject
Pointer to a variable that receives the address of the device object for the disk device object.

Return Value

IoGetDiskDeviceObject returns one of the following status values:

STATUS_INVALID_PARAMETER
One of the parameters passed to this function was invalid.
STATUS_VOLUME_DISMOUNTED
STATUS_SUCCESS

Comments

IoGetDiskDeviceObject returns a pointer to the storage device object associated with the file system volume. The storage device need not be an actual disk

File system filter drivers typically call IoGetDiskDeviceObject for a file system volume device object to determine whether the volume is mounted.

IoGetDiskDeviceObject increments the reference count on the disk device object pointed to by DeviceObject. Thus every successful call to IoGetDiskDeviceObject must be matched by a subsequent call to ObDereferenceObject.

Requirements

Versions: This routine is available on Update Rollup for Windows 2000 Service Pack 4 (SP4) and on Windows XP and later.

IRQL: <=DISPATCH_LEVEL

Headers: Declared in ntifs.h. Include ntifs.h.

반응형
반응형

개발하고 있는 파일 시스템 필터 드라이버 ...


일단 기본기능은 구현했다만,,,이놈 저놈 테스트시마다 문제가 발생한다.

이번에 만난 문제는 Windows2000에서의 구동문제다.

Sfilter
를 기반으로한 드라이버이고, WindowsXP Vista에서는 정상 구동...

Windows 2000의 경우, 이미 로드된 파일시스템 드라이버에 대한 통지를 받지 못한다고 하니,
추가 코드가 필요하려니 하긴 했지만, 예상치 못한 문제가 발생한다.

1. 첫번째 문제 - SLIST ( 이건 파일시스템 필터와 관련된건 아니지만)
드라이버를 설치하고 로드하려고 하니 아래와 같은 메시지를 뱉어내며, 로딩이 안된다.


뭔가 Win2k에서 지원하지 않는 함수를 쓴거 같기는 한데...
네이버에 물어보니 ExFreeToNPagedLookasideList()와 관련이 있단다. 내부적으로 SList관련 함수를 쓰는 모양이다
.

그렇지만 의문이 생기는 것은 Sfilter도 동일한 함수를 사용했지만, Sfilter 드라이버는 win2k에서 로딩이 된다는 거다
..
하나 하나 추적하며 테스트 해보니, 결국 ExFreeToNPagedLookasideList()을 사용한 코드가 문제이긴 했다
.
원인이 뭘까
?

----------------------------------------------------------------------------------------------------
Sfilter
에는 다음의 구문이 존재한다. Win2k에서 SList를 쓰기위한 먼가의 정의 인거 같다.

#ifndef _WIN2K_COMPAT_SLIST_USAGE
#define _WIN2K_COMPAT_SLIST_USAGE
#endif


우선 문제의 해결은 위의 구문을 헤더에 추가해 주거나, Sorces파일에 다음 구문을 추가해 주면 된다.

C_DEFINES=$(C_DEFINES) -D_WIN2K_COMPAT_SLIST_USAGE

그리고 원인을 찾고 나니 눈에 띄는 ExFreeToNPagedLookasideList() 관련 DDK문서의 내용...
On Microsoft Windows 2000, drivers must use the
D_WIN2K_COMPAT_SLIST_USAGE switch to successfully link code that uses ExFreeToPagedLookasideList

그런데.. ExFreeToNPagedLookasideList 도 똑같구만.. ExFreeToNPagedLookasideList
섹션에는 커맨트를 빼먹어서 사람을 혼란스럽게 하냔 말이다
.
(
역시 소스를 참고할때는 꼼꼼해 살펴봐야 손가락이 고생안한다. )


----------------------------------------------------------------------------------------------------
위와 같이 처리하는 이유는 wdm.h에 존재하는 아래의 코드 때문이다.

#if defined(_WIN2K_COMPAT_SLIST_USAGE) && defined(_X86_)
NTKERNELAPI
PSLIST_ENTRY
FASTCALL
ExInterlockedPopEntrySList (
__inout PSLIST_HEADER ListHead,
__inout __deref __drv_neverHold(KeSpinLockType) PKSPIN_LOCK Lock
);

NTKERNELAPI
PSLIST_ENTRY
FASTCALL
ExInterlockedPushEntrySList (
__inout PSLIST_HEADER ListHead,
__inout __drv_aliasesMem PSLIST_ENTRY ListEntry,
__inout __deref __drv_neverHold(KeSpinLockType) PKSPIN_LOCK Lock
);

#else

#define ExInterlockedPopEntrySList(ListHead, Lock) \
InterlockedPopEntrySList(ListHead)
#define ExInterlockedPushEntrySList(ListHead, ListEntry, Lock) \
InterlockedPushEntrySList(ListHead, ListEntry)

#endif

* 2011.05.04 추가


2. 두번째 문제 Filter Group
Sfilter
샘플을 보면, 드라이버의 필터 그룹을 "FSFilter Activity Monitor"로 설정한다.
(Windows 2000
에는 "FSFilter Activity Monitor"그룹이 없다던데
....)
MS
에서 만든 샘플이니 일단 따라해 봤다
.
등록도 되고 잘 동작하는듯 보였는데
...
파일 생성/Read/Write 모두 필터링이 안되는 문제가 발생했다
.
확인해 보니 Ntfs드라이버가 생성한 DeviceObject Attach가 안된다
.
Ntfs
파일시스템 등록시 통지를 해주지는 않는 듯 하다
.

필터 그룹을 "Filter"로 해서 등록하니 이제야 정상 동작.

 

규격에 끼워맞춰 코딩하는건 참 지난한 작업인 것 같다.

 

반응형
반응형

IRP_MJ_MAXIMUM_FUNCTION

 

아래에 이어서 파일시스템 필터 드라이버 등록시 발생한 문제.

 

파일 시스템 드라이버로 등록한 후 재 부팅...

이번에는 문제 없겠지...?

 

하지만 이번에도 발생한 애매모호한 문제...

 

재 부팅시 아래와 같은 메시지가 팝업 되는거다.

 

 

뜬금없이 왠 페이징 사이즈??

 

처음에는 드라이버에서 사용하는 전역변수 크기가 너무 큰지?

드라이버 코드가 메모리를 넘 마니 잡아먹는지?

에 초점을 맞춰 봤지만, 이래 저래 코드를 빼봐도 마찬가지 였다.

 

그러던중, 시스템의 페이징 사이즈 정보를 보니 0으로 설정되어 있는게 아닌가?

 

좀 쪽 팔린 얘기지만 이 문제 확인하면서, 윈도우즈가 페이징 처리하는 대상 파일이 Pagefile.sys라는걸 알았다.

 

그렇담... 이놈을 읽거나 쓰는 게 문제가 아닐까?

역시나 디버깅을 해보니, 내가 작성한 드라이버가 C드라이브에 볼륨에 Attach되면 pagefile.sys Create할때 몇 번의 에러가 발생하는 게 아닌가?

 

이번에도 Sfilter와 비교해가며, Attach하는 부분을 싹 다 점검하고, 코드를 하나하나 빼가며 확인하기 시작했다.

 

문제의 원인은??? .

바로 이코드다...

for ( i = 0; i < IRP_MJ_MAXIMUM_FUNCTION; i++ )

{

  DriverObject->MajorFunction[i] = DispathPassthru;

}

 

무슨 문제인지 감이 오십니껴????

 

i < IRP_MJ_MAXIMUM_FUNCTION 가 아니라 i <= IRP_MJ_MAXIMUM_FUNCTION 로 작성해야 하는 코드였다.

 

ntddk.h파일을 보면

IRP_MJ_CREATE( 0x00 )에서 시작해서

IRP_MJ_PNP( 0x1b ) 까지 정의가 되어 있다.

그런데 IRP_MJ_MAXIMUM_FUNCTION의 값은 0x1c가 아니라  0x1b인거다.

 

MajorFunction[] 배열을 모두 DispathPassthru로 채워주자면

 i <= IRP_MJ_MAXIMUM_FUNCTION 인경우까지 루프를 돌려줘야 한다.

 

직접적인 연관 관계는 알 수 없지만, IRP_MJ_PNP에 대한 디스패치 함수가 등록되지 않아 발생한 문제로 보여진다.

 

이 문제 확인하는데 1주일이 걸리긴 했지만...

그래도 pagefile.sys에 대한 내용과 DriverObject->MajorFunction[]를 채우는 부분에 대해

머리속 깊이 각인되었으니 그나마 다행...

 

그래도 되도록이면 삽질하지 말자..

 

 

반응형
반응형

Device Naming

 

첫번째 개발 프로젝트인 파일시스템 드라이버...

하나씩 확인해 가며 개발하려니 만만치가 않군...

 

워쨌든 간에 좀 보완해야 할 부분은 있지만, 기본 구조와 기능들은 이래 저래 시행착오를 겪어가며 개발했다.

 

이제 이놈을 드라이버 타입을 파일시스템으로 해서 등록하고, 로드 시점을 시스템 부팅 시 올라오도록 등록만 하는 되는데...

 

역시나, 한번에 되는게 없다..^
드라이버 서비스 등록 시 파일시스템 드라이버 타입으로 등록하니, 잘 돌아가던 드라이버가 로드가 안되는게지...

오류 메시지는... 이미 있는 놈이라 생성을 할 수 없단다...

 

Sfilter 방식으로도 설치해보고, 이래저래 비교를 해봤건만... 미궁....

 

고생 고생해서 확인하고 나니...

Control DeviceObject의 이름문제였다.

 

원래 지정했던 이름은 \\FileSystem\\XXXX

그런데 파일시스템 드라이버 타입으로 등록하면, 드라이버 이름도 \\FileSystem\\XXX로 등록된다는 사실...

 

드라이버 이름과 Control Device 이름이 같아서 발생한 문제였다.

 

* 디바이스 이름 명명시 Device Device간 뿐만 아니라 DeviceDriver 이름 또한 중복된 이름을 만들면 안 된다.

지금 생각하면 당연한 건데 ㅡ.

 

이전 버전 드라이버 개발했던 분이,

작성한 파일 시스템 필터 드라이버의 CDO이름을  \\FileSystem\\XXX로 등록하니 안 되서 \\FileSystem\\XXX0로 했다고 하더니 같은 문제더라. 머 이런 얘기다.

 

반응형
반응형

 

메모리를 할당한 후 반드시 리턴값을 확인 할 것

 

커널 메모리가 소진되어 메모리를 더 이상 할당 할 수 없는 경우가 발생할 가능성이 얼마나 될까?

드라이버 관련 유지보수 및 개발담당한지 7개월 남짓이지만,

간간히 레포트가 들어오는 사항이다.

첫번째로 레포트된 문제는 인계받은 드라이버 쪽에서의 메모리 누수로 인한 메모리 할당 실패...
(
찾느라 애좀 먹었다.. 위대하신 PoolTag님의 도움으로 겨우 해결.)
이 경우야 우리 드라이버의 문제이므로, 변명의 여지 없음이고....

그 외에도 ExAllocatePool() 호출이 실패하여 NULL이 리턴되고,
NULL 포인터에 메모리를 쓰려다가 발생한 BSOD도 심심찬게 레포트 된다.


메모리 할당 후 리턴값을 확인하는 것은 왜 필요한가?

내가 작성한 드라이버가 아닌 다른 드라이버가 커널 메모리를 누수시키며 동작하고 있다고 가정하자.

이 문제의 드라이버 때문에 어느 순간인가 메모리 할당이 실패할 것이고,

그렇게 되면 우리 드라이버는 메모리 할당이 실패한 줄도 모르고 잘못된 메모리를 참조하여,
우리 드라이버가 요주의 용의자로 지목되는 BSOD가 발생할 가능성이 다분하다.

그러면 어찌될지는 뻔한 일이다. 분명 우리 드라이버의 문제가 아님에도 우리 쪽으로 버그 레포트가 올테고 우리 드라이버의 문제가 아님을 증명하기 위해 시간과 노력을 투자할 밖에....

이런 의미에서 메모리 할당후에 정상적으로 할당되었는지 확인하는 것은 아주 기본적이지만 중요한 습관이다.

새로 작성하는 코드 전체에 할당 성공 여부를 확인하는 코드를 삽입하고,
DriverVerifier
Low Resource Simulation 옵션을 를 체크하여 테스트 해보니
BSOD
없이 잘 구동된다.....

다만 이경우, 메모리 할당 실패로 우리의 드라이버가 정상적인 동작을 할 수 없을 가능성이 다분하므로, 이러한 상황을 확인 할 수 있는 별도의 조치가 필요하리라..

 

반응형

+ Recent posts