alg : 单向链表逆序 on drv

算法参考: http://blog.sina.com.cn/s/blog_4c1934d5010093ky.html


算法的思路:

  遍历原始链表, 摘出每个元素, 作为新链表的头节点. 上一次摘出的原始链表元素作为本次摘出元素的Next节点.

  当遍历完原始链表后, 新的链表就是逆序的单向链表.

  我考虑了单向链表为回环的情况, 在驱动层实现了一次.

  实验过了, 回环和非回环单向链表逆序都正常.


单链表逆向的实现:

BOOLEAN ListReverse(PNODE * ppNodeHead)
{
    BOOLEAN bListIsLoop     =   FALSE;
    size_t  nElementsCnt    =   0;
    PNODE   pNodeCur        =   NULL;   ///< 当前链表节点
    PNODE   pNodeNext       =   NULL;   ///< 下一链表节点
    PNODE   pNodeTail       =   NULL;

    PNODE   pListNewHead    =   NULL;
    PNODE   pListNewTail    =   NULL;

    NT_ASSERT(NULL != ppNodeHead);
    NT_ASSERT(NULL != *ppNodeHead);

    /// 计算单向链表的元素个数N, 可以使此链表逆序算法适用于链表"回环"或"不回环"的情况
    bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail);   ///< 不关心链表是否回环, 只需要链表元素个数
    if (nElementsCnt <= 1)
        return TRUE;    ///< 链表节点2个以上, 才需要逆序

    /// 遍历原始链表, 摘出每个元素, 作为新列表的头节点
    /// 返回的头节点是最后一个元素

    pNodeCur = *ppNodeHead;
    do 
    {
        pNodeNext = pNodeCur->pNext;
        if (NULL == pListNewHead)
        {
            /// 新List的尾节点是原始List的头节点
            pListNewTail = pNodeCur;
            pListNewTail->pNext = NULL;
            pListNewHead = pListNewTail;
        }
        else
        {
            pNodeCur->pNext = pListNewHead;
            pListNewHead = pNodeCur;
        }

        pNodeCur = pNodeNext;
        ShowList(&pListNewHead);
    } while (nElementsCnt-- > 1);

    if (bListIsLoop)
        pListNewTail->pNext = pListNewHead; ///< 处理回环情况

    *ppNodeHead = pListNewHead;
    ShowList(&pListNewHead);
    return TRUE;
}

运行结果

>> DriverEntry 
======================================== 
ShowList >> pNodeHead = 0x8674E930 
  pNodeHead->data = 0x0, pNodeHead->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x8690CE00
  pNodeCur = 0x8690CE00, pNodeCur->data = 0x4, pNodeCur->pNext = 0x86529190
  pNodeCur = 0x86529190, pNodeCur->data = 0x5, pNodeCur->pNext = 0x8674E930
======================================== 
ShowList >> pNodeHead = 0x8674E930 
  pNodeHead->data = 0x0, pNodeHead->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x85F0D8B8 
  pNodeHead->data = 0x1, pNodeHead->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x86C31548 
  pNodeHead->data = 0x2, pNodeHead->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x85E96AB8 
  pNodeHead->data = 0x3, pNodeHead->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x8690CE00 
  pNodeHead->data = 0x4, pNodeHead->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x86529190 
  pNodeHead->data = 0x5, pNodeHead->pNext = 0x8690CE00
  pNodeCur = 0x8690CE00, pNodeCur->data = 0x4, pNodeCur->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x00000000
======================================== 
ShowList >> pNodeHead = 0x86529190 
  pNodeHead->data = 0x5, pNodeHead->pNext = 0x8690CE00
  pNodeCur = 0x8690CE00, pNodeCur->data = 0x4, pNodeCur->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x86529190
======================================== 
ShowList >> pNodeHead = 0x86529190 
  pNodeHead->data = 0x5, pNodeHead->pNext = 0x8690CE00
  pNodeCur = 0x8690CE00, pNodeCur->data = 0x4, pNodeCur->pNext = 0x85E96AB8
  pNodeCur = 0x85E96AB8, pNodeCur->data = 0x3, pNodeCur->pNext = 0x86C31548
  pNodeCur = 0x86C31548, pNodeCur->data = 0x2, pNodeCur->pNext = 0x85F0D8B8
  pNodeCur = 0x85F0D8B8, pNodeCur->data = 0x1, pNodeCur->pNext = 0x8674E930
  pNodeCur = 0x8674E930, pNodeCur->data = 0x0, pNodeCur->pNext = 0x86529190
ppNode is invalid
<< DriverEntry 


完整实现:

/// @file           sys.c
/// @brief          驱动主程序

#include <ntddk.h>
#include "Function.h"

#define MODULE_NAME         L"DrvDemo"
#define DRIVER_NAME         MODULE_NAME L".sys"
#define DEVICE_NAME_GLOBAL  L"\\\\.\\" MODULE_NAME
#define DEVICE_NAME         L"\\device\\" MODULE_NAME
#define LINK_NAME           L"\\dosDevices\\" MODULE_NAME

#define LISTNODE_CNT        6       ///< 单向链表节点数量
#define IS_LIST_LOOP        TRUE    ///< 单向链表是否回环

NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp);
VOID DriverUnload(PDRIVER_OBJECT pDriverObject);

NTSTATUS DriverEntry(IN PDRIVER_OBJECT pDriverObject, 
                     IN PUNICODE_STRING pRegPath)
{
    size_t          nIndex          =   0;
    NTSTATUS        ntStatus        =   STATUS_SUCCESS;

    PDEVICE_OBJECT  pDeviceObject = NULL;

    UNICODE_STRING  ustrDeviceName = {0};
    UNICODE_STRING  ustrLinkName = {0};

    PNODE   pNode       =   NULL;

    DbgPrint(">> DriverEntry\r\n");

    RtlInitUnicodeString(&ustrDeviceName, DEVICE_NAME);
    RtlInitUnicodeString(&ustrLinkName, LINK_NAME);

    ntStatus = IoCreateDevice(
        pDriverObject, 
        0, 
        &ustrDeviceName, 
        FILE_DEVICE_UNKNOWN, 
        0, 
        FALSE, 
        &pDeviceObject);
    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("<< DriverEntry : error IoCreateDevice\r\n");
        return ntStatus;
    }

    pDeviceObject->Flags |= DO_BUFFERED_IO;
    ntStatus = IoCreateSymbolicLink(
        &ustrLinkName, 
        &ustrDeviceName);
    if (!NT_SUCCESS(ntStatus))
    {
        DbgPrint("<< DriverEntry : error IoDeleteDevice\r\n");
        IoDeleteDevice(pDeviceObject);
        return ntStatus;
    }

    for(nIndex = 0; nIndex < IRP_MJ_MAXIMUM_FUNCTION; nIndex++)
    {
        pDriverObject->MajorFunction[nIndex] = DispatchCommon;
    }

    pDriverObject->DriverUnload = DriverUnload;

    /// 建立链表(节点数量, 是否回环)
    CreateList(&pNode, LISTNODE_CNT, IS_LIST_LOOP);
    ShowList(&pNode);

    /// 单向链表逆序
    ListReverse(&pNode);
    ShowList(&pNode);

    /// 释放链表
    RemoveList(&pNode);
    ShowList(&pNode);

    DbgPrint("<< DriverEntry\r\n");

    return STATUS_SUCCESS;
}

VOID DriverUnload(PDRIVER_OBJECT pDriverObject)
{
    UNICODE_STRING ustrLinkName = {0};

    DbgPrint(">> DriverUnload\r\n");

    RtlInitUnicodeString(&ustrLinkName, LINK_NAME);
    IoDeleteDevice(pDriverObject->DeviceObject);
    IoDeleteSymbolicLink(&ustrLinkName);

    DbgPrint("<< DriverUnload\r\n");
}

NTSTATUS DispatchCommon(PDEVICE_OBJECT pDeviceObject, PIRP pIrp)
{
    pIrp->IoStatus.Information = 0;
    pIrp->IoStatus.Status = STATUS_SUCCESS;

    IoCompleteRequest(pIrp, IO_NO_INCREMENT);

    return STATUS_SUCCESS;
}

/// @file           Function.h
/// @brief          功能的实现

#ifndef __FUNCTION_H__
#define __FUNCTION_H__

#include <ntddk.h>
#include <WINDEF.H>

// for warning C4996: 'ExAllocatePool': was declared deprecated
#pragma warning(disable:4996)

typedef struct _node
{
    int data;
    struct _node * pNext;
} NODE,*PNODE;

/// 外部接口
/// @fn         ListReverse
/// @brief      单向链表翻转
BOOLEAN ListReverse(PNODE * ppNodeHead);

/// 内部接口

/// @fn         CreateList
/// @brief       建立一个单向链表
/// @param      PNODE * ppNode, 链表首节点指针, *ppNode 必须为空
/// @param      size_t nListSize, 链表的元素个数
/// @param      BOOLEAN bIsListLoop, 是否创建单回环链表, 如果是, 该链表首尾相接
void CreateList(PNODE * ppNode, size_t nListSize, BOOLEAN bIsListLoop);

void RemoveList(PNODE * ppNode);
void ShowList(PNODE * ppNode);

/// @fn         IsListLoop
/// @brief      链表是否回环
/// @param      IN PNODE * ppNodeHead, 单向链表头指针
/// @param      OUT size_t * pnElementsCnt, 单向链表的元素计数
/// @param      OUT PNODE * ppNodeTail, 单向链表尾指针
/// @return     BOOLEAN
/// @retval     TRUE, 链表回环
/// @retval     FALSE, 不是回环链表
/// @note OUT size_t & nElementsCnt 编译不过 ?
BOOLEAN IsListLoop(IN PNODE * ppNodeHead, OUT size_t * pnElementsCnt, OUT PNODE * ppNodeTail);

#endif

/// @file           Function.c
/// @brief          功能的实现

#include "Function.h"

void CreateList(PNODE * ppNode, size_t nListSize, BOOLEAN bIsListLoop)
{
    PNODE   pNodeHead   =   NULL;
    PNODE   pNodeCur    =   NULL;
    size_t  nIndex      =   0;

    if ((NULL == ppNode) || (NULL != *ppNode) || (nListSize < 1))
    {
        return;
    }

    pNodeHead = (PNODE)ExAllocatePool(NonPagedPool, sizeof(NODE));
    pNodeHead->data = 0;
    pNodeHead->pNext = NULL;
    *ppNode = pNodeHead;

    pNodeCur = pNodeHead;
    for (nIndex = 1; nIndex < nListSize; nIndex++)
    {
        pNodeCur->pNext = (PNODE)ExAllocatePool(NonPagedPool, sizeof(NODE));
        
        pNodeCur = pNodeCur->pNext;
        pNodeCur->data = nIndex;
        pNodeCur->pNext = NULL;
    }

    if (bIsListLoop)
        pNodeCur->pNext = pNodeHead; ///< 形成单链表回环
}

void ShowList(PNODE * ppNode)
{
    PNODE   pNodeCur    =   NULL;
    PNODE   pNodeHead   =   NULL;

    if ((NULL == ppNode) || (NULL == *ppNode))
    {
        DbgPrint("ppNode is invalid\n");
        return;
    }

    pNodeHead = *ppNode;

    DbgPrint("========================================\r\n");
    DbgPrint("ShowList >> pNodeHead = 0x%p\r\n", pNodeHead);
    DbgPrint("\t pNodeHead->data = 0x%x, pNodeHead->pNext = 0x%p\n", pNodeHead->data, pNodeHead->pNext);

    pNodeCur = pNodeHead->pNext;
    while ((NULL != pNodeCur) && (pNodeCur != pNodeHead))
    {
        DbgPrint("\t pNodeCur = 0x%p, pNodeCur->data = 0x%x, pNodeCur->pNext = 0x%p\n",
            pNodeCur, pNodeCur->data, pNodeCur->pNext);
        pNodeCur = pNodeCur->pNext;
    }
}

void RemoveList(PNODE * ppNode)
{
    PNODE   pNodeHead   =   NULL;
    PNODE   pNodeCur    =   NULL;
    PNODE   pNodeNext   =   NULL;

    if ((NULL == ppNode) || (NULL == *ppNode))
    {
        return;
    }

    pNodeHead = *ppNode;

    /// 释放头节点之外的数据
    pNodeCur = pNodeHead->pNext;
    while ((NULL != pNodeCur) && (pNodeCur != pNodeHead))
    {
        pNodeNext = pNodeCur->pNext;
        ExFreePool(pNodeCur);
        pNodeCur = pNodeNext;
    }

    /// 释放头节点
    ExFreePool(pNodeHead);
    *ppNode = NULL;
}

BOOLEAN IsListLoop(IN PNODE * ppNodeHead, OUT size_t * pnElementsCnt, OUT PNODE * ppNodeTail)
{
    BOOLEAN bFind       =   FALSE;
    PNODE   pNodeCur    =   NULL;
    PNODE   pNodeHead   =   NULL;

    NT_ASSERT(NULL != ppNodeHead);
    NT_ASSERT(NULL != *ppNodeHead);
    NT_ASSERT(NULL != pnElementsCnt);
    NT_ASSERT(NULL != ppNodeTail);

    pNodeHead = *ppNodeHead;
    pNodeCur = pNodeHead->pNext;

    *ppNodeTail = pNodeCur;
    (*pnElementsCnt)++;

    while (NULL != pNodeCur)
    {
        if (pNodeCur == pNodeHead)
        {
            bFind = TRUE;
            break;
        }

        *ppNodeTail = pNodeCur;
        pNodeCur = pNodeCur->pNext;
        (*pnElementsCnt)++;
    }

    return bFind;
}

BOOLEAN ListReverse(PNODE * ppNodeHead)
{
    BOOLEAN bListIsLoop     =   FALSE;
    size_t  nElementsCnt    =   0;
    PNODE   pNodeCur        =   NULL;   ///< 当前链表节点
    PNODE   pNodeNext       =   NULL;   ///< 下一链表节点
    PNODE   pNodeTail       =   NULL;

    PNODE   pListNewHead    =   NULL;
    PNODE   pListNewTail    =   NULL;

    NT_ASSERT(NULL != ppNodeHead);
    NT_ASSERT(NULL != *ppNodeHead);

    /// 计算单向链表的元素个数N, 可以使此链表逆序算法适用于链表"回环"或"不回环"的情况
    bListIsLoop = IsListLoop(ppNodeHead, &nElementsCnt, &pNodeTail);   ///< 不关心链表是否回环, 只需要链表元素个数
    if (nElementsCnt <= 1)
        return TRUE;    ///< 链表节点2个以上, 才需要逆序

    /// 遍历原始链表, 摘出每个元素, 作为新列表的头节点
    /// 返回的头节点是最后一个元素

    pNodeCur = *ppNodeHead;
    do 
    {
        pNodeNext = pNodeCur->pNext;
        if (NULL == pListNewHead)
        {
            /// 新List的尾节点是原始List的头节点
            pListNewTail = pNodeCur;
            pListNewTail->pNext = NULL;
            pListNewHead = pListNewTail;
        }
        else
        {
            pNodeCur->pNext = pListNewHead;
            pListNewHead = pNodeCur;
        }

        pNodeCur = pNodeNext;
        ShowList(&pListNewHead);
    } while (nElementsCnt-- > 1);

    if (bListIsLoop)
        pListNewTail->pNext = pListNewHead; ///< 处理回环情况

    *ppNodeHead = pListNewHead;
    ShowList(&pListNewHead);
    return TRUE;
}







你可能感兴趣的:(alg : 单向链表逆序 on drv)