Есть драйвер который шарит свою память в юзермод. Клиентское приложение обращается к драйверу через посулку IOCTL запроса, а тот в свою очередь должен вернуть в буфере адрес расшаренной памяти. Вот код обработки запроса в драйвере: Код (Text): inputBuffer = Irp->AssociatedIrp.SystemBuffer; inputBufferLength = irpStack->Parameters.DeviceIoControl.InputBufferLength; outputBuffer = Irp->AssociatedIrp.SystemBuffer; outputBufferLength = irpStack->Parameters.DeviceIoControl.OutputBufferLength; switch (ioControlCode) { // ... case GET_SHARED_MEMORY: if (outBufferLength >= sizeof(PVOID)) { *(PVOID*)outputBuffer = ShareMem(PAGE_SIZE*4); } break; // ... } В клиентском приложение делаю так: Код (Text): PVOID lpSharedMem = NULL; DeviceIoControl(m_hDev_, GET_SHARED_MEMORY, &lpSharedMem, sizeof(PVOID), &lpSharedMem, sizeof(PVOID), &ReturnedLength, NULL); // lpSharedMem всегда равен нулю if (lpSharedMem == NULL) return FALSE; После вызова DeviceIoControl переменная lpSharedMem остается равной нуля, хотя при отладке драйвера видно что в буфер записывается значение отличное от нуля. GET_SHARED_MEMORY определен так: Код (Text): #define GET_SHARED_MEMORY CTL_CODE(FILE_DEVICE_TEST, FIRST_IOCTL_INDEX + 103, METHOD_BUFFERED, FILE_ANY_ACCESS) В чем тут может быть дело???
IO Manager может не отмапливать системный буфер на пользовательский, если у хендла нет нужных прав. См. есть ли у тебя флаг GENERIC_READ (или более специфичный read-флаг) в вызове CreateFile. ЗЫ: IMHO, в данном случае входных данных нет, поэтому параметры 3 и 4 в DeviceIoControl излишне вредны.
собственно вот Код (Text): m_hDev_ = CreateFile(DevName, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, 0, NULL);
GetLastError после DeviceIoControl что говорит? Ну и проверь есть ли. Irp->IoStatus.Status = STATUS_SUCCESS; Irp->IoStatus.Information = sizeof(PVOID); IoCompleteRequest( Irp, IO_NO_INCREMENT );
Four-F, Great про Irp->IoStatus.Information я что забыл... оно у меня всегда равно нулю... Завтра проверю что будет если правлиьно заполню.. А как это мжет повлиять на то что пишется или в буфер данные??? Просто я думал что это чисто дополнительно-информативные данные... т.е. на работу драйвера не могут так повлиять...
Читай подробнее под буферизированный ввод-вывод у драйвера. Вообщем, в двух словах дело обстоит так. В IO Control Code задается метод ввода-вывода, у тебя он как раз равен METHOD_BUFFERED, то есть ты используешь буферизированный ввод-вывод. Менеджер ввода-вывода при вызове DeviceIoControl -> ZwDeviceIoControlFile видит это и выделяет системный буфер в ядерных адресах, размер которого равен наибольшему из указанных размеров входного и выходного буферов. Дальше в него копируется входной буфер и вызывается Dispatch-функция драйвера для IRP_MJ_DEVICE_CONTROL. Дальше, главное! При завершении IRP менеджер ввода-вывода смотрит число Irp->IoStatus.Information - там драйвер должен указать число байт, которые он записал в системный буфер. Именно это число байт он скопирует в пользовательский выходной буффер. Если оно равно нулю, НИЧЕГО в выходном буфере ты не обнаружишь. За подробностями Welcome to MSDN & статьи Four-F'а про драйвера.
Забыл сказать, что тоже самое действует при буферизированном вводе (или выводе) в операциях записи (чтения) по IRP_MJ_WRITE (IRP_MJ_READ), соответственно.
Интересно а почему именно столько, а не все что есть в буфере... ведь туда уже все записанно и врядли я копировав туда 10 байт захочу чтоб в юзер мод попало всего 9...
Смотри, например у тебя размер входного буфера 20 байт, а выходного 15 байт. Менеджер ввода-вывода выделит системный буфер размером MAX(20,15)=20 байт и скопирует туда содержимое входного буфера. Дальше что ты ему прикажешь делать то? Ему нужно знать сколько драйвер туда реально записал байтов? Как он может скопировать все содержимое буфера (20 байт) в юзермодный выходной буфер (15 байт) ? А вдруг буфер выделен с запасом и реально туда записано должно быть только 4 байта? Для этого как раз в Irp->IoStatus.Information драйвер должен записать, сколько байт менеджер должен скопировать в выходной буфер.
все равно как-то не логично... пусть копит не 20, а 15 а то что с запасом это уже дело клиента... он сам разберется.... А вот кстати если я в Irp->IoStatus.Information запишу 25 вместо максимума в 15, то что IO менеджер деалть будет...
Не помню насчет того, есть ли там проверки. Но лучше так не делать. Обычно размер выходного буфера проверяют вначале и ругаются, если его не хватает. Что значит разберется? Вполне логично. Представь, что драйвер может отдать по каким-то там своим причинам от 4 до 8 байт данных. Я конечно же задаю выходной буфер 8 байт. Как изволите мне дальше определять сколько байт реально вернул драйвер, а сколько скопировано "с запасом" ? Как раз ReturnedLength - последний (кажется) параметр DeviceIoControl и берется из этого поля Irp->IoStatus.Information И ничего нелогичного я не вижу
Ну просто избыточность некоторая получается... Можно например весь буфер забить нулями и тогда точно будешь знать сколько байт пришло от драйвера... Вообщем еслиб я писал ядро, я бы по другому сделал
DeeoniS Я еще раз пытаюсь пояснить что избыточности нет. В любом случае нужно знать, сколько байт вернул драйвер. Ты же не знаешь сколько он вернет заранее (за искл. реедких случаев) и выделяешь буфер побольше, чтобы все вместилось если что. Поэтому тебе нужно как-то узнать, сколько он тебе вернул. И никакой избыточности я не вижу.. Хорошо, предложи действительно более разумный вариант. Four-F Да уж