Советую почитать Walter Oney 2nd .. ТАМ очень по дробно описано про эти списки . Картинки приведены. Примеры реализации в ядре. Я приведу вам код.. но там нет ничего ТАКОГО. (Пс писал по памяти. могут быть ошибки..) Так же добавил синхронизацию... (для полного счастья) Вначале делаем инициализацию: Код (Text): g_NPagedLookasideList = (PNPAGED_LOOKASIDE_LIST)ExAllocatePool(NonPagedPool,sizeof(NPAGED_LOOKASIDE_LIST)); if (NULL==g_NPagedLookasideList) { DBGPRINT0("Error ExAllocatePool for Lookaside list!"); return STATUS_MY_ERROR; } ExInitializeNPagedLookasideList(g_NPagedLookasideList,NULL,NULL,0,sizeof(MEMBLOC_LIST),'ms',0); InitializeListHead(&g_ListHead); DBGPRINT0("init mutex"); KeInitializeMutex(&g_Mutex, 0); Далее есть функция добавления элемента в список: Код (Text): void AddToList(PMDL pBkpMdl, PELEM pElem) { PVOID pResult; pResult = ExAllocateFromNPagedLookasideList(g_NPagedLookasideList); if (pResult!=NULL) { memset(pResult,0,sizeof(MEMBLOC_LIST)); KeWaitForMutexObject(&g_Mutex,Executive,KernelMode,FALSE,NULL); InsertHeadList(&g_ListHead,&((PMEMBLOC_LIST)pResult)->ListEntry); ((PMEMBLOC_LIST)pResult)->pMdlRez = pBkpMdl; ((PMEMBLOC_LIST)pResult)->pElemRez = pElem; KeReleaseMutex(&g_Mutex,FALSE); } else DBGPRINT0("Error ExAllocateFromNPagedLookasideList() !"); return; } Далее процедура Поиска элемента : Код (Text): PLIST_ENTRY CheckListElem(PELEM pDelElem) { KeWaitForSingleObject(&g_Mutex,Executive,KernelMode,FALSE,NULL); PLIST_ENTRY pRezEntry = g_ListHead.Flink, pBkpEntry = &g_ListHead; do { PVOID Entry = CONTAINING_RECORD(pRezEntry,MEMBLOC_LIST,ListEntry); DBGPRINT2("ELEM : %x == %x",pDelElem,((PMEMBLOC_LIST)Entry)->pElemRez); if (((PMEMBLOC_LIST)Entry)->pElemRez == pDelElem) { KeReleaseMutex(&g_Mutex,FALSE); return pRezEntry; } pRezEntry = pRezEntry->Flink; } while(pRezEntry->Flink!=pBkpEntry); KeReleaseMutex(&g_Mutex,FALSE); return NULL; } Ну и процедура удаления (Очень примитивная - просто удаляет элемент) : Код (Text): VOID RemoveEntry() { if (IsListEmpty(&g_ListHead)!=TRUE) { KeWaitForMutexObject(&g_Mutex,Executive,KernelMode,FALSE,NULL); MmUnlockPages(((PMEMBLOC_LIST)&g_ListHead)->pMdlRez); IoFreeMdl (((PMEMBLOC_LIST)&g_ListHead)->pMdlRez); ExFreePool(((PMEMBLOC_LIST)&g_ListHead)->pElemRez); PLIST_ENTRY pLink = RemoveHeadList(&g_ListHead); PVOID Entry = CONTAINING_RECORD(pLink,MEMBLOC_LIST,ListEntry); ExFreeToNPagedLookasideList(g_NPagedLookasideList,Entry); KeReleaseMutex(&g_Mutex,FALSE); } else DBGPRINT0("List is Empty!"); } В общем приблизительно так... Народ, код не критиковать - писал с ходу. Структура MEMBLOC_LIST - содержит 2 элемента это когдато выделеный mdl и elem.
DoZENT: после ExInitializePagedLookasideList должна ОБЯЗАТЕЛЬНО следовать ExDeletePagedLookasideList!!!!
TermoSINteZ, так lookaside list можно что ли использовать?? Или все это под двусвязный переписывать надо?
Просто на первой странице помнится lookaside list забраковали по причине выделения данных только определенного размера. Ну ОК, попробую с ними поработать, если что не получится напишу. В любом случае спасибо.
Ну если вам нужен переменный размер, то тогда надо другие функции использовать. Типа InitializeListHead, InsertTailList,IsListEmpty,RemoveHeadList. В той книге, что я говорил, это все описано.
Сделал точно так же как в примере выше, работает через раз(( Т.е.: приложение ring3 посылает драйверу строку А, он ее принимает, проверяет есть ли такая строка в листе, ее ессно нет, => записывает в лист норамально. Потом посылает точно такую же строку А, в драйвер принимает, проверяет ее наличие, говорит, что такая строка уже есть => в список ее не включает. Затем посылается еще одна строка B, драйвер говорит, что такой еще нет и записывает ее в лист. До этого момента все нормально. Но если после всего этого еще раз послать строку А, то драйвер скажет, что в листе ее нет и добавит!!. При освобождении листа кол-во удаляемых элементов = 3. Почему первый раз функция IsAdded сработала нормально, а второй раз нет?? Кстати, если в этой функции при пробеге всех элементов написать что-то типа DbgPrint ("Item: %S", ((POBJECT_DATA)Entry)->str), то в отладке вылезет Item (null). Я тут начал рассматривать такой вариант (откопал на сайте): Код (Text): typedef struct _ProcessList { PVOID NextItem; HANDLE Pid; } TProcessList, *PProcessList; BOOLEAN IsAdded(PProcessList List, HANDLE Pid) { PProcessList Item = List; while (Item) { if (Pid == Item->Pid) return TRUE; Item = Item->NextItem; } return FALSE; } void DelItem(PProcessList *List, HANDLE Pid) { PProcessList Item = *List; PProcessList Prev = NULL; while (Item) { if (Pid == Item->Pid) { if (Prev) Prev->NextItem = Item->NextItem; else *List = Item->NextItem; ExFreePool(Item); return; } Prev = Item; Item = Item->NextItem; } return; } void FreePointers(PProcessList List) { PProcessList Item = List; PVOID Mem; while (Item) { Mem = Item; Item = Item->NextItem; ExFreePool(Mem); } return; } void AddItem(PProcessList *List, HANDLE Pid) { PProcessList wNewItem; wNewItem = ExAllocatePool(NonPagedPool, sizeof(TProcessList)); wNewItem->NextItem = *List; *List = wNewItem; wNewItem->Pid = Pid; return; } Как я понял - это односвязный список? Но здесь тип элемента - HANDLE. Насколько корректно данные функции будут работать с PWSTR или с UNICODE_STRING? В самом начале пробовал использовать эти функции, но с ними была такая проблема: когда пробегаешь список элементов первые секунд 5 все ОК, а потом в отладочном окне вместо строки вылезали крякозябры. З.Ы. Прошу прощения за столько вопросов)
DoZENT Во первых, для двусвязного списка используются структуры типа LIST_ENTRY. То есть ссылка и в перед и назад. По поводу твоего IsAdded ничего особого сказать не могу. Проверял алгоритм ваш - работает (проверял не в ядре - но не суть важно). Видимо у вас ошибка с выделением памяти или что-то в том же духе А вообще советую вначале все такие вещи проверяйте в юзере, а потом их переводить в ядро. Во вторых обязательно проверяйте ExAllocatePool на ошибку. По поводу элемента - все будет верно работать если верно выделять память для элементов.. И следите за указателями Вот код ваш проверял в студии (немного изменив): Напишу только то что проверял Код (Text): #include <stdio.h> #include <Windows.h> typedef struct _ProcessList { PVOID NextItem; int Pid; } TProcessList, *PProcessList; BOOLEAN IsAdded(PProcessList List, int Pid) { PProcessList Item = List; while (Item) { if (Pid == Item->Pid) return TRUE; Item = (TProcessList*)Item->NextItem; } return FALSE; } void AddItem(PProcessList *List, int Pid) { PProcessList wNewItem; wNewItem = (TProcessList*)malloc(sizeof(TProcessList)); wNewItem->NextItem = *List; *List = wNewItem; wNewItem->Pid = Pid; return; } int main() { TProcessList GList; GList.NextItem = 0; GList.Pid = 0; PProcessList pList = 0; for (int i = 0; i<=10; i++) AddItem((PProcessList*)&GList,i); pList = &GList; for (int i = 0; i<=10; i++) { printf("Elem pid = %d\n",pList->Pid); pList = (PProcessList)pList->NextItem; } pList = &GList; for (int i = 0; i<=10; i++) if (IsAdded(&GList,i)) printf("Elem <%d> is added\n",i); return 0; } В итоге Код (Text): Elem pid = 0 Elem pid = 10 Elem pid = 9 Elem pid = 8 Elem pid = 7 Elem pid = 6 Elem pid = 5 Elem pid = 4 Elem pid = 3 Elem pid = 2 Elem pid = 1 Elem <0> is added Elem <1> is added Elem <2> is added Elem <3> is added Elem <4> is added Elem <5> is added Elem <6> is added Elem <7> is added Elem <8> is added Elem <9> is added Elem <10> is added Press any key to continue