В драйвере перехватываю различные api функции, собираю с каждой нужные мне параметры. Возник вопрос, куда девать взятые мною данные (например имя открываемого файла, id завершаемого процесса и т.д.). Т.е. необходим какой-то аналог TList (как в делфе). Прочитал Драйверы режима ядра: Часть 7: Работа с памятью. Использование ассоциативных списков , пытаюсь сделать что-то подобное на C: При загрузке драйвера: Код (Text): g_PagedList = ExAllocatePool (NonPagedPool, sizeof (PAGED_LOOKASIDE_LIST)); if (g_PagedList != NULL) { ExInitializePagedLookasideList (g_PagedList,NULL,NULL,0, sizeof(ObjectsList),'msaW',0); DPRINT("LookasideList: Lookaside list initialized\n"); InitializeListHead (g_ListHead); //без этой строки выполняется } else DPRINT("LookasideList: Couldn't allocate nonpaged memory for lookaside list control structure"); Комп перезагружается. В чем дело? И еще, как мне пройтись по всем элементам списка или узнать количество элементов в списке?
все только ручками Весь смысл этих функций в быстром отдавании памяти тебе. А уж заполнение контентом и, тем более, хождение по элементам только самостоятельно.
OK, но пока я даже выделить память под лист не могу(( При выполнении InitializeListHead (g_ListHead) копм делает ребут((
LIST_ENTRY A LIST_ENTRY structure describes an entry in a doubly-linked list or serves as the header for such a list. typedef struct _LIST_ENTRY { struct _LIST_ENTRY *Flink; struct _LIST_ENTRY *Blink; } LIST_ENTRY, *PLIST_ENTRY; Members Flink For a LIST_ENTRY structure that serves as a list entry, the Flink member points to the next entry in the list or to the list header if there is no next entry in the list. For a LIST_ENTRY structure that serves as the list header, the Flink member points to the first entry in the list or to the LIST_ENTRY structure itself if the list is empty. Blink For a LIST_ENTRY structure that serves as a list entry, the Blink member points to the previous entry in the list or to the list header if there is no previous entry in the list. For a LIST_ENTRY structure that serves as the list header, the Blink member points to the last entry in the list or to the LIST_ENTRY structure itself if the list is empty. Куда g_ListHead кажет?
Ужас какой. Такого ремикса я ещё не видел DoZENT, ты же смешал воедино две абсолютно разные сущности: lookaside list и doubly linked list! Это не одно и то же. Код из первого поста сразу ф топку. Примеры приводить не буду, т.к. буквально в каждом исходнике в DDK используется doubly linked list и примеры использования lookaside list тоже можно найти в том же DDK.
Извиняюсь, невнимательно смотрел. Привидилось, что g_PagedList и g_ListHead - это одна и таже переменная. Тогда ОК, микса нету, но lookaside list в данном случае не подойдет, т.к. куски памяти будут разного размера. Так что просто ExAllocatePool. Инициализировать doubly linked list так: LIST_ENTRY g_ListHead; InitializeListHead( &g_ListHead ); Остальное лучше глянуть в DDK.
Извиняюсь, не понял Так какого размера куски памяти то будут? И если разного, то почему так нельзя сделать? Я же буду хранить данные в структуре фиксированного размера.
В документации про пятый параметр функции ExInitializePagedLookasideList написано: Specifies the size in bytes of each entry in the lookaside list. Поэтому, если инициализировать ассоциативный список так ExInitializePagedLookasideList (g_PagedList,NULL,NULL,0, sizeof(ObjectsList),'msaW',0); то ExAllocateFromPagedLookasideList будет возвращать куски памяти размером sizeof(ObjectsList). И изменить размер динамически нельзя. Из ассоциативного списка можно выделять только определенный при инициализации размер. Это не вяжется с твоим первым постом: "Возник вопрос, куда девать взятые мною данные (например имя открываемого файла,...)." Имя файла в принципе не может иметь фиксированную длину. Мало того, длина имен файлов может отличаться в разы и более. Так что не получается структур фиксированного размера. Ну если только они не будут размером, равным максимально возможному размеру имени файла, но в этом случае большая часть памяти будет болтаться без дела.
ОК, это понятно, спасибо. Сейчас DDK читаю, немного не понял, что такое KSPIN_LOCK, KeInitializeSpinLock и т.д.? Типа для синхронизации? Обязательно ли в моем случае это дело использовать?
К сожелению, нет времени отвечать на каждый вопрос, а их, я так понимаю будет ещё очень много Могу посоветовать прочитать книгу Walter Oney "Programming the Microsoft Windows Driver Model, Second Edition" в подлиннике или перевод http://www.piter.com/book/978591180057/ (качество перевода оценить не могу - в руках ещё не держал).
Угу. Если один поток, то нет. Но для перехвата API желательно использовать в самом перехватчике, если ты собираешься работать со списками.
Кто-нибудь может написать пусть не код, конечно, но простейший алгоритм работы с двойными списками? Действия, которые мне нужны в принципе: I) инициализировать список, II) вставить в него элемент, III)удалить из него элемент, IV)проверить существование элемента Как я понял: Объявляем структуру Код (Text): typedef struct _SOME_STRUCT { UNICODE_STRING FileName; LIST_ENTRY listHead; // head pointer } SOME_STRUCT, *PSOME_STRUCT; I) 1. InitializeListHead( &some_structVar->listHead ); //Это все? II) 1. InsertHeadList (&some_structVar->listHead, Points to an entry to be inserted in the list) Что должно быть вторым параметром? Мне нужно вставить структуру данных типа SOME_STRUCT, а мне предлагают PLIST_ENTRY.. Объясните дураку, чего-то туплю я. III) 1. RemoveHeadList (&some_structVar->listHead); Так удалится структура, которая лежит на самой верхушке листа (последняя, добавленная). А если мне надо удалить ту, которая в середине? IV) Вообще не знаю… Заранее спасибо. P.S. Чувствую, что чего-то не понял в корне, просто раньше работал исключительно с делфами, так привык к тамошнему TList, TStringList, что что-то другое уже плохо воспринимается((
Есть у меня эта книга в электронном виде, почему-то не обращал на нее внимание. Действительно, надо почитать, там про списки есть?
Имхо лучше listHead в начало структуры положить. Чтобы указатель на LIST_ENTRY совпадал с указателем на структуру. Кроме этогоне listHead, а ListEntry. Нет. Есть глобальная переменная listHead, её и надо инициализировать. Элемент который ты добавляешь. То есть тебе надо Код (Text): InitializeListHead(ListHead, &some_structVar->listEntry ); RemoveEntryList(). Параметр - указатель на тот элемент который тебе надо удалить. Перебрать все элементы. Могу схемку нарисовать. Хотя можешь посмотреть схему связи EPROCESS. Правда не помню в какой статье её встречал.
А в предложенной выше книжке написано так: Код (Text): typedef struct _DEVICE_EXTENSION { LIST_ENTRY IrpQueue; BOOLEAN DeviceBusy; } DEVICE_EXTENSION, *PDEVICE_EXTENSION; NTSTATUS AddDevice(...) { InitializeListHead(&pdx->IrpQueue); } Кому верить?)