2014 dxdy logo

Научный форум dxdy

Математика, Физика, Computer Science, Machine Learning, LaTeX, Механика и Техника, Химия,
Биология и Медицина, Экономика и Финансовая Математика, Гуманитарные науки




 
 Проблема - MmGetSystemAddressForMdlSafe и ProbeForRead
Сообщение16.08.2010, 23:32 
Следующий код в драйвере обрабатывающий IRP запрос:
Используется синтаксис C++
 
#define CtlCodeCopy CTL_CODE(FILE_DEVICE_UNKNOWN, 0x801, METHOD_OUT_DIRECT, FILE_ANY_ACCESS)
 

- генерирует исключение при обращении к выходному буферу режма ядра, а именно функция ProbeForRead :

код: [ скачать ] [ спрятать ]
Используется синтаксис C++
 
NTSTATUS Handler801(IN PDEVICE_OBJECT pDeviceObject, IN PIRP Irp, PIO_STACK_LOCATION pSL)
{
        DbgPrint("Handler801");
        PVOID pOutBuff = MmGetSystemAddressForMdlSafe (Irp->MdlAddress,HighPagePriority);
if (pOutBuff != NULL)
{
__try
 {
     ProbeForRead(pOutBuff, Irp->MdlAddress->ByteCount, TYPE_ALIGNMENT(char));
     DbgPrint("Handler801 : __try");
 }
__except (EXCEPTION_EXECUTE_HANDLER)
 {
    DbgPrint("Handler801 : __except");
    return STATUS_MEMORY_NOT_ALLOCATED;
 }
}
        Irp->IoStatus.Information = 0 ;
        return STATUS_SUCCESS;
}
 


Указатель pOutBuff не NULL, почему функция ProbeForRead вызывает исключение не пойму.
Вот лог DebugView - содержимое структур IO_STACK_LOCATION и IRP, тут всё в порядке:
00000000 0.00000000 DriverDeviceControl
00000001 0.00000301 OutputBufferLength=4096
00000002 0.00000425 InputBufferLength=4096
00000003 0.00000555 IoControlCode=2236422
00000004 0.00000669 Type3InputBuffer=0

00000005 0.00000815 Irp->MdlAddress->ByteCount=4096
00000006 0.00000939 Irp->MdlAddress->Size=32
00000007 0.00001070 Irp->MdlAddress->ByteOffset=0
00000008 0.00001207 Irp->MdlAddress->StartVa=17305600
00000009 0.00001321 IoCtl=801

Вот текст программы посылающей запрос драйверу:
код: [ скачать ] [ спрятать ]
Используется синтаксис C++
 
hDevice = CreateFile("\\\\.\\MyDevice0",  // drive to open
                    GENERIC_READ | GENERIC_WRITE,
                    FILE_SHARE_READ |   // share mode
                    FILE_SHARE_WRITE,
                    NULL,                         // default security attributes
                    OPEN_EXISTING,        // disposition
                    0,                              // file attributes
                    NULL);                       // do not copy file attributes
if (hDevice == INVALID_HANDLE_VALUE) // cannot open the drive
  { return;}
...

 LPVOID lpReserv = VirtualAlloc(NULL,
                                 SystemInfo.dwAllocationGranularity,
                                 MEM_RESERVE,
                                 PAGE_READWRITE);
 LPVOID lpCommitIn = VirtualAlloc(lpReserv,
                                   SystemInfo.dwPageSize,
                                   MEM_COMMIT,
                                   PAGE_READWRITE);
  LPVOID lpCommitOut = VirtualAlloc((LPVOID) ((DWORD)lpReserv + SystemInfo.dwPageSize),
                                    SystemInfo.dwPageSize,
                                    MEM_COMMIT,
                                    PAGE_READWRITE);
...
BOOL bResult = DeviceIoControl(hDevice,  // device to be queried
                                                  CtlCodeCopy,                    // operation to perform
                                                  lpCommitIn,                       // input buffer
                                                  SystemInfo.dwPageSize,    // input buffer
                                                  lpCommitOut,                    // output buffer
                                                  SystemInfo.dwPageSize,     // output buffer
                                                  &junk,                                 // # bytes returned
                                                  (LPOVERLAPPED) NULL);     // synchronous I/O

... Do something ...

  CloseHandle(hDevice);
  VirtualFree(lpCommitOut,0,MEM_DECOMMIT);
  VirtualFree(lpCommitIn,0,MEM_DECOMMIT);
  VirtualFree(lpReserv,0,MEM_RELEASE);

  return ;
 

 
 
 
 Re: Проблема - MmGetSystemAddressForMdlSafe и ProbeForRead
Сообщение17.08.2010, 08:46 
Может так: т.к. TransferType = METHOD_OUT_DIRECT, по адресу Irp->MdlAddress - буфер вывода (для драйвера) и, соответственно, созданный MDL доступен только на запись.

 
 
 
 Re: Проблема - MmGetSystemAddressForMdlSafe и ProbeForRead
Сообщение17.08.2010, 09:24 
Пробовал по отдельности и ProbeForWrite и ProbeForRead и с выходным и с входным буфером, результат тот же, генерируется исключение:
Используется синтаксис C++
 
__try
 {
       //ProbeForRead(pOutBuff, Irp->MdlAddress->ByteCount, TYPE_ALIGNMENT(char));
        ProbeForWrite(pOutBuff, Irp->MdlAddress->ByteCount, TYPE_ALIGNMENT(char));
        //ProbeForRead(Irp->AssociatedIrp.SystemBuffer, pSL->Parameters.DeviceIoControl.InputBufferLength, 1);
        //ProbeForWrite(Irp->AssociatedIrp.SystemBuffer, pSL->Parameters.DeviceIoControl.InputBufferLength, 1);
 }
 

 
 
 
 Re: Проблема - MmGetSystemAddressForMdlSafe и ProbeForRead
Сообщение17.08.2010, 15:02 
Давайте разбираться.
При обработке DeviceIoControlTransferType=METHOD_xx_DIRECT) система создает MDL, который описывает физические страницы памяти, относящиеся к буферу ввода/вывода и фиксирует (lock) эти страницы в памяти. Драйвер использует MmGetSystemAddressForMdlSafe для отображения этих страниц в свое (kernel-mode) адресное пространство. Но функции ProbeForRead и ProbeForWrite используются только для проверки буферов памяти в пользовательском (user-mode) адресном пространстве:
Windows DDK писал(а):
ProbeForRead
...
Do not use this routine on kernel-mode addresses; it will raise an exception.
...
Вот если бы использовался METHOD_NEITHER...

См. подробности - User-Mode Interactions: Guidelines for Kernel-Mode Drivers.

 
 
 
 Re: Проблема - MmGetSystemAddressForMdlSafe и ProbeForRead
Сообщение17.08.2010, 15:44 
Точно, спасибо lim0n, как это я сам не обратил внимания, бывает...
- "If the specified range of memory is not within the user-mode address range, ProbeForRead raises the STATUS_ACCESS_VIOLATION exception. "
А я же передавал в эту функцию виртуальный адрес kernel-mode .

Попробовал записать строку из user-mode во входной буфер, передал в дравер, и потом в драйвере вернул эту строку в выходной буфер и распечатал в user-mode - всё работает !
Спаибо за помощь !

 
 
 [ Сообщений: 5 ] 


Powered by phpBB © 2000, 2002, 2005, 2007 phpBB Group