全部博文(282)
分类: WINDOWS
2008-05-24 19:51:46
unit LookasideList;
interface
uses
nt_status, ntoskrnl, macros;
function _DriverEntry(pDriverObject: PDRIVER_OBJECT;
pusRegistryPath: PUNICODE_STRING): NTSTATUS; stdcall;
implementation
type
PSOME_STRUCTURE = ^SOME_STRUCTURE;
SOME_STRUCTURE = record
SomeField1: DWORD;
SomeField2: DWORD;
{ . . .} {这里放入一些别的字段}
ListEntry: LIST_ENTRY; {主角^_^,可以放在结构的开始}
{放在这里是为了演示的需要}
{ . . .} {这里放入一些别的字段}
SomeFieldX: DWORD;
end;
var
g_pPagedLookasideList: PPAGED_LOOKASIDE_LIST;
g_ListHead: LIST_ENTRY;
g_dwIndex: DWORD;
dwCnt: DWORD;
procedure AddEntry;
var
pEntry: PSOME_STRUCTURE;
begin
{从后备列表中分配内存块}
pEntry := ExAllocateFromPagedLookasideList(g_pPagedLookasideList);
if pEntry <> nil then
begin
DbgPrint('LookasideList: + Memory block allocated from lookaside list at address %08X'#13#10, pEntry);
{初始化分配到的内存}
memset(pEntry, 0, sizeof(SOME_STRUCTURE));
{一个节点可以添加到链表的头部、尾部或者其他地方,视个人喜好了}
{本例添加到表头}
InsertHeadList(@g_ListHead, @pEntry^.ListEntry);
{使用SomeField1保存表项的索引. 这是为了让我们能看见它在工作.}
inc(g_dwIndex);
pEntry^.SomeField1 := g_dwIndex;
DbgPrint('LookasideList: + Entry #%d added'#13#10, pEntry^.SomeField1);
end else
begin
DbgPrint('LookasideList: Very bad. Couldn''t allocate from lookaside list'#13#10);
end;
end;
procedure RemoveEntry;
var
pEntry, pTemp: pointer;
ss: SOME_STRUCTURE;
offs: DWORD;
begin
if IsListEmpty(@g_ListHead) <> TRUE then
begin
{删除表项也一样,可以从头、尾或者其他地方删除,}
{这里我们还是从头部开始删除.}
{计算offs是因为RemoveHeadList返回的是SOME_STRUCTURE.ListEntry的地址}
{offs就是SOME_STRUCTURE.ListEntry到结构开始处的偏移量}
offs := DWORD(@ss.ListEntry) - DWORD(@ss);
{这里pEntry ==> SOME_STRUCTURE.ListEntry}
{我们需要得到指向包含这个ListEntry的SOMT_STRUCTURE结构的指针}
{以便释放内存,用pEntry - offs即可得到结构的指针.}
pEntry := RemoveHeadList(@g_ListHead);
{pTemp ==> SOME_STRUCTURE,这里一定要弄明白}
pTemp := pointer(DWORD(pEntry) - offs);
DbgPrint('LookasideList: - Entry #%d removed'#13#10,
PSOME_STRUCTURE(pTemp)^.SomeField1);
{向后备列表归还不用的内存}
ExFreeToPagedLookasideList(g_pPagedLookasideList, pTemp);
DbgPrint('LookasideList: - Memory block at address %08X returned to lookaside list'#13#10, pTemp);
end else
begin
DbgPrint('LookasideList: - An attempt was made to remove entry from empty lookaside list'#13#10);
end;
end;
function _DriverEntry(pDriverObject: PDRIVER_OBJECT;
pusRegistryPath: PUNICODE_STRING): NTSTATUS; stdcall;
begin
DbgPrint(#13#10'LookasideList: Entering DriverEntry'#13#10);
g_pPagedLookasideList := ExAllocatePool(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST));
if g_pPagedLookasideList <> nil then
begin
DbgPrint('LookasideList: Nonpaged memory for lookaside list allocated at address %08X'#13#10,
g_pPagedLookasideList);
ExInitializePagedLookasideList(g_pPagedLookasideList, nil,
nil, 0, sizeof(SOME_STRUCTURE),
$6D736157{'msaW'}, 0);
DbgPrint('LookasideList: Lookaside list initialized'#13#10);
InitializeListHead(@g_ListHead);
DbgPrint('LookasideList: Doubly linked list head initialized'#13#10);
DbgPrint(#13#10'LookasideList: Start to allocate/free from/to lookaside list');
g_dwIndex := 0;
dwCnt := 0;
while dwCnt < 5 do
begin
AddEntry;
AddEntry;
RemoveEntry;
inc(dwCnt);
end;
while true do
begin
RemoveEntry;
if IsListEmpty(@g_ListHead) = true then
begin
DbgPrint('LookasideList: List is empty'#13#10#13#10);
break;
end;
end;
{后备列表已清空,销毁之}
ExDeletePagedLookasideList(g_pPagedLookasideList);
DbgPrint('LookasideList: Lookaside list deleted'#13#10);
ExFreePool(g_pPagedLookasideList);
DbgPrint('LookasideList: Nonpaged memory for lookaside list at address %08X released'#13#10,
g_pPagedLookasideList);
end else
begin
DbgPrint('LookasideList: Couldn''t allocate nonpaged memory for lookaside list control structure');
end;
DbgPrint('LookasideList: Leaving DriverEntry'#13#10);
result := STATUS_DEVICE_CONFIGURATION_ERROR;
end;
end.
g_pPagedLookasideList := ExAllocatePool(NonPagedPool, sizeof(PAGED_LOOKASIDE_LIST));
if g_pPagedLookasideList <> nil then
begin
ExInitializePagedLookasideList(g_pPagedLookasideList, nil,
nil, 0, sizeof(SOME_STRUCTURE),
$6D736157{'msaW'}, 0);
InitializeListHead(@g_ListHead);
g_dwIndex := 0;
dwCnt := 0;
while dwCnt < 5 do
begin
AddEntry;
AddEntry;
RemoveEntry;
inc(dwCnt);
end;
while true do
begin
RemoveEntry;
if IsListEmpty(@g_ListHead) = true then
begin
DbgPrint('LookasideList: List is empty'#13#10#13#10);
break;
end;
end;
ExDeletePagedLookasideList(g_pPagedLookasideList);
ExFreePool(g_pPagedLookasideList);
result := STATUS_DEVICE_CONFIGURATION_ERROR;
pEntry := ExAllocateFromPagedLookasideList(g_pPagedLookasideList);
if pEntry <> nil then
begin
InsertHeadList(@g_ListHead, @pEntry^.ListEntry);
inc(g_dwIndex);
pEntry^.SomeField1 := g_dwIndex;
if IsListEmpty(@g_ListHead) <> TRUE then
begin
offs := DWORD(@ss.ListEntry) - DWORD(@ss);
pTemp := pointer(DWORD(pEntry) - offs);
ExFreeToPagedLookasideList(g_pPagedLookasideList, pTemp);