Windows OS2013. 5. 19. 16:50
반응형

디스크 볼륨이 ReadOnly인지 확인할 필요가 있어 찾다보니 FltIsVolumeWritable()이라는 함수를 발견했다.

기쁨도 잠시...

Vista 이상만 지원하기 때문에 XP에서는 사용할 수가 없었다.

 

그래서...

XP에서도 동작하게 하기 위해 FltIsVolumeWritable() 함수를 구현하기로 했다.

FltIsVolumeWritable() 내부를 보니 생각보다 복잡하지 않았기 때문이다.


 

Windows 7 SP1


kd> uf fltmgr!FltIsVolumeWritable

fltmgr!FltIsVolumeWritable:

8489a398 8bff            mov     edi,edi

8489a39a 55              push    ebp

8489a39b 8bec            mov     ebp,esp

8489a39d 83ec18          sub     esp,18h

8489a3a0 53              push    ebx

8489a3a1 56              push    esi

8489a3a2 8b7508          mov     esi,dword ptr [ebp+8] ; FltObject(Volume)

8489a3a5 57              push    edi

8489a3a6 8b7d0c          mov     edi,dword ptr [ebp+0Ch] ; IsWritable(Ptr)

8489a3a9 c60701          mov     byte ptr [edi],1 ; IsWritable=1

8489a3ac 8b06            mov     eax,dword ptr [esi] ; Volume.Base.Flags

8489a3ae 8bc8            mov     ecx,eax

8489a3b0 c1e918          shr     ecx,18h ; Check bit 0x18

8489a3b3 f6c101          test    cl,1

8489a3b6 7405            je      fltmgr!FltIsVolumeWritable+0x25 (8489a3bd) ; No bit 0x18


fltmgr!FltIsVolumeWritable+0x20: ; bit 0x18

8489a3b8 8b7618          mov     esi,dword ptr [esi+18h]

8489a3bb eb07            jmp     fltmgr!FltIsVolumeWritable+0x2c (8489a3c4)


fltmgr!FltIsVolumeWritable+0x25:

8489a3bd c1e81a          shr     eax,1Ah ; Check bit 0x1A

8489a3c0 a801            test    al,1

8489a3c2 7470            je      fltmgr!FltIsVolumeWritable+0x9c (8489a434) ; No bit 0x1A 


fltmgr!FltIsVolumeWritable+0x2c: ; bit 0x1A

8489a3c4 33db            xor     ebx,ebx ; ebx=0

8489a3c6 395e20          cmp     dword ptr [esi+20h],ebx ; Volume.DiskDeviceObject

8489a3c9 7507            jne     fltmgr!FltIsVolumeWritable+0x3a (8489a3d2) ; jmp if exist


fltmgr!FltIsVolumeWritable+0x33:

8489a3cb b819001cc0      mov     eax,0C01C0019h ; STATUS_FLT_NO_DEVICE_OBJECT

8489a3d0 eb67            jmp     fltmgr!FltIsVolumeWritable+0xa1 (8489a439)


fltmgr!FltIsVolumeWritable+0x3a:

8489a3d2 53              push    ebx

8489a3d3 53              push    ebx

8489a3d4 8d45e8          lea     eax,[ebp-18h] ; KEVENT

8489a3d7 50              push    eax

8489a3d8 ff1528208884    call    dword ptr [fltmgr!_imp__KeInitializeEvent (84882028)]

8489a3de 8d45f8          lea     eax,[ebp-8]

8489a3e1 50              push    eax

8489a3e2 8d45e8          lea     eax,[ebp-18h] ; KEVENT

8489a3e5 50              push    eax

8489a3e6 53              push    ebx ; 0

8489a3e7 53              push    ebx ; 0

8489a3e8 53              push    ebx ; 0

8489a3e9 53              push    ebx ; 0

8489a3ea 53              push    ebx ; 0

8489a3eb ff7620          push    dword ptr [esi+20h] ; Volume.DiskDeviceObject

8489a3ee 6824000700      push    70024h ; IOCTL_DISK_IS_WRITABLE

8489a3f3 ff15b8238884    call    dword ptr [fltmgr!_imp__IoBuildDeviceIoControlRequest (848823b8)]

8489a3f9 3bc3            cmp     eax,ebx ; Irp

8489a3fb 7507            jne     fltmgr!FltIsVolumeWritable+0x6c (8489a404)


fltmgr!FltIsVolumeWritable+0x65:

8489a3fd b89a0000c0      mov     eax,0C000009Ah

8489a402 eb35            jmp     fltmgr!FltIsVolumeWritable+0xa1 (8489a439)


fltmgr!FltIsVolumeWritable+0x6c:

8489a404 8b4e20          mov     ecx,dword ptr [esi+20h] ; Volume.DiskDeviceObject

8489a407 8bd0            mov     edx,eax ; Irp

8489a409 ff15b4218884    call    dword ptr [fltmgr!_imp_IofCallDriver (848821b4)]

8489a40f 3d03010000      cmp     eax,103h ; STATUS_PENDING

8489a414 7511            jne     fltmgr!FltIsVolumeWritable+0x8f (8489a427) ; jmp if not


fltmgr!FltIsVolumeWritable+0x7e: ; STATUS_PENDING

8489a416 53              push    ebx ; 0

8489a417 53              push    ebx ; 0

8489a418 53              push    ebx ; 0

8489a419 53              push    ebx ; 0

8489a41a 8d45e8          lea     eax,[ebp-18h] ; KEVENT

8489a41d 50              push    eax

8489a41e ff1504248884    call    dword ptr [fltmgr!_imp__KeWaitForSingleObject (84882404)]

8489a424 8b45f8          mov     eax,dword ptr [ebp-8]


fltmgr!FltIsVolumeWritable+0x8f:

8489a427 3da20000c0      cmp     eax,0C00000A2h ; STATUS_MEDIA_WRITE_PROTECTED

8489a42c 7502            jne     fltmgr!FltIsVolumeWritable+0x98 (8489a430) ; jmp if not


fltmgr!FltIsVolumeWritable+0x96: ; STATUS_MEDIA_WRITE_PROTECTED

8489a42e 881f            mov     byte ptr [edi],bl ; IsWritable=0


fltmgr!FltIsVolumeWritable+0x98:

8489a430 33c0            xor     eax,eax ; STATUS_SUCCESS

8489a432 eb05            jmp     fltmgr!FltIsVolumeWritable+0xa1 (8489a439)


fltmgr!FltIsVolumeWritable+0x9c:

8489a434 b80d0000c0      mov     eax,0C000000Dh


fltmgr!FltIsVolumeWritable+0xa1:

8489a439 5f              pop     edi

8489a43a 5e              pop     esi

8489a43b 5b              pop     ebx

8489a43c c9              leave

8489a43d c20800          ret     8



 

이렇게 보고 나서 대충 비슷하게 C로 구현하니 다음과 같이 나왔다.

 

NTSTATUS
IsVolumeWritable(
IN   PVOID pFltVolume,
OUT  PBOOLEAN pbWritable
{

NTSTATUS ntStatus = STATUS_UNSUCCESSFUL;

PDEVICE_OBJECT pDiskDevObj = NULL;
KEVENT kEvent;
PIRP pIrp = NULL;
IO_STATUS_BLOCK IoStatusBlock;

if (NULL == pFltVolume || NULL == pbWritable)
{
return STATUS_INVALID_PARAMETER;
}

 

*pbWritable = TRUE;

  

ntStatus = FltGetDiskDeviceObject( pFltVolume, &pDiskDevObj );
if (FALSE == NT_SUCCESS(ntStatus))
{
return ntStatus;
}

KeInitializeEvent( &kEvent, NotificationEvent, FALSE );

pIrp = IoBuildDeviceIoControlRequest( IOCTL_DISK_IS_WRITABLE,
                                                             pDiskDevObj,
                                                             NULL, 0, NULL, 0, FALSE,
                                                             &kEvent,
                                                             &IoStatusBlock );
if (NULL == pIrp)
{
ObDereferenceObject( pDiskDevObj );
return STATUS_INSUFFICIENT_RESOURCES;
}

ntStatus = IoCallDriver( pDiskDevObj, pIrp );
if (STATUS_PENDING == ntStatus)
{
KeWaitForSingleObject( &kEvent, Executive, KernelMode, FALSE, NULL );
ntStatus = IoStatusBlock.Status;
}

if (STATUS_MEDIA_WRITE_PROTECTED == ntStatus)
{
*pbWritable = FALSE;
}
 

ObDereferenceObject( pDiskDevObj );


return STATUS_SUCCESS;

구현 완료!
 


반응형
Posted by GreeMate