算法参考: 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; }