本论坛为只读模式,仅供查阅,不能注册新用户,不能发帖/回帖,有问题可发邮件 xikug.xp (^) gmail.com
查看: 46024|回复: 165

放个稳定完整的磁盘还原代码2k-win7的(加上分析) [复制链接]

Rank: 1

发表于 2010-3-19 12:36:25 |显示全部楼层
经N次改动已经很稳定,给用的上的人,放硬盘里只会让他长毛
详细的介绍
http://diskflt.googlecode.com
> 支持2000 xp 2003 vista win7
> 不在磁盘上产生任何临时文件
> 超优化的算法,在保护的情况下,操作硬盘,跟没有保护的情况下,速度一样, 不伤硬盘
> 模拟硬件还原卡工作原理,稳定快速
> 密码保护,用户登录后可以任意配置还原选项
> 支持只保护系统盘,和全盘保护, 支持多硬盘
> 保护MBR,加入防机器狗模块,用户可以手头关闭拦截第三方驱动的功能,比如用来完一些带驱动保护的游戏(以后改成白名单)
> 所有功能,集成到一个驱动文件里,全绿色免安装,一共一个文件
> 界面简洁,操作方便,没任何副作用,呵呵, 我诚认界面是学习迅闪的,以前用习惯它了,不过它不防狗
> 更改了下算法,应付内存特别小的情况 V1.3
>忘更新了,加了第三方驱动加载时拦截确认对话框有点鸡肋
> 当然,以上介绍有部分夸大之词

应sysnap提义,下午没事,写了下原理
磁盘还原原理, 以后下拙见,可能有些地方高手有异义,请指出

两种方法
1:卷过滤
2:磁盘过滤
3:hook磁盘IRP分发函数

第一种方法,2k下不适用, 但写起来比较省事
第二种方法,通用,写起来不太省事
第三种方法,算了,我没见过哪个稳定商业的还原软件放着好好的上两种方法不用,用HOOK的, HOOK好用,不能乱用啊
衡量了一下,用第二种

准备工作 :

一个磁盘过滤框架,如diskperf, 或者其它的

开始加代码

磁盘读写,独立出来一个回调
用线程分发,保证读写在同一个线程里,为了稳定,毕竟,都知道多线程只对应用层好使
但低层硬件操作,大家都还得排队,啥时候发展到硬盘一个柱面一个磁头了,就能放开跑了

驱动加载后,读配置,我把配置写到自身了,省事,不想再写别的文件

获取要保护卷的位图,有两种方法
1: FSCTL_GET_VOLUME_BITMAP
2: 自己分析NTFS和FAT格式,NTFS的比较好获取,FAT的我查了点资料,源码放我blog上
  http://www.dbgger.com/?id=765

分析以上两种方法:
第一种的缺点:
  如果系统盘为NTFS,那么系统启动的时候,会挂载NTFS解析器,这时候,如果其它分区不是跟系统盘相同的
  分区格式FSCTL_GET_VOLUME_BITMAP获取其它分区会获取失败,不很完美
第二种的缺点:
    显而易见,FAT16 extfat这些格式,都要分析,加大了复杂度,还有一个很不爽的原因,动态磁盘,没办法很好操作
    因为系统动盘磁盘有一个专门的驱动,这玩意儿只会在需要的时候挂载,比如E为动态磁盘,系统启动完成后,你访问E
    盘他才会加载, 这时候我想起卷过滤的好了,不过已经到着了,索性继续写下去

考虑以上两种方法,第一种,对动态磁盘支持不太好,但有一个挽救的方法,就是等系统启动后,再访问一下动态磁盘分区,再获取位图
这样也算是亡羊补牢了,第二种,代码复杂度很大,缺点也不少,考虑用第一种

继续写:
  磁盘位图以簇为单位,比如要保护C盘吧,需要准备一些工作
  1: 获取C盘位图
  2: 建立一个新位图,做为保护一些需要放过的文件用,但要用扇区为单位, 原因有二
    A: 磁盘读写最小单位为扇区
    B: 为了减少代码复杂度,因为比如说,上层要写512字节,如果你以簇为单位,在重定位就需要做一些不必要的工作,接着向下看就知道了
    bootstat.dat pagefile.sys hiberfil.sys 这三个需要放过,后两个也许大家都知道是干啥的,我只说下第一个
    第一个是系统在记动后写入启动是否成功的标志,要是不放过他,重启后,xp及以后的系统会提示上次非正常关机之类的, 详细说明见http://www.dbgger.com/?id=758
  3: 建立一个重定向位图,同样以扇区为单位, 标记着哪些扇区让重定向了,这个不用说了,充当着稀疏文件的句柄
  4: 建立一个重定向表,用NTDLL的GenericTable, 查找扇区被重定向到哪里
  以前准备工作做好了以后,基本上就是操作位图了,这里有个跟代码效率有关的话题
  位图是一次性申请完,还是一段段申请,如果一个分区有200G, 重定向位图,跟要放过指定文件的位图,就要占,来算一下,(200 * 1024 * 1024 * 1024) / 512 / 8 / 1024 / 1024 = 50M, 50M内存,还是连续的,算了吧,太大了,申请不成功,就完了,还是多写几  行,分块来存 位图吧,分块就是,把位图表始的范围,分成几个区域,当然越多越好,这个有点像简单的hash map, 比如,你需要访问指定扇区  的 时候,查找下  这个扇区所在的位图是否已经建立,如果已经建立,就使用,没建立,就申请,初始化

下面放上系统的核心代码,一些尽在代码中。看注释应该很明白:


// 初始化工作,获取磁盘扇区个数,还有FAT逻辑簇前的扇区个数
  1. NTSTATUS
  2. flt_initVolumeLogicBitMap(PVOLUME_INFO volumeInfo)
  3. {
  4.     NTSTATUS    status;
  5.     PVOLUME_BITMAP_BUFFER    bitMap = NULL;   
  6.     // 逻辑位图大小
  7.     ULONGLONG    logicBitMapMaxSize = 0;
  8.    
  9.     ULONG        sectorsPerCluster = 0;
  10.     ULONGLONG    index = 0;
  11.     ULONGLONG    i = 0;
  12.     status = flt_getVolumeBitmapInfo(volumeInfo->volume, &bitMap);
  13.    
  14.     if (!NT_SUCCESS(status))
  15.     {
  16.         return status;
  17.     }
  18.     sectorsPerCluster = volumeInfo->bytesPerCluster / volumeInfo->bytesPerSector;
  19.     // 获取此卷上有多少个扇区, 用bytesTotal这个比较准确,如果用其它的比如fsinfo,会少几个扇区发现
  20.     volumeInfo->sectorCount = volumeInfo->bytesTotal / volumeInfo->bytesPerSector;
  21.    
  22.     // 得到逻辑位图的大小bytes
  23.     logicBitMapMaxSize = (volumeInfo->sectorCount / 8) + 1;
  24.     ........
  25.    
  26.     // 这几个需要放过写入的文件,获取所在的扇区,专门弄一张位图放进去
  27.     setBitmapDirectRWFile(volumeInfo->volume,
  28.         (*NtBuildNumber >= 2600) ? L"\\Windows\\bootstat.dat" : L"\\WINNT\\bootstat.dat",
  29.         volumeInfo->bitMap_Protect);
  30.     // 页面文件
  31.     setBitmapDirectRWFile(volumeInfo->volume, L"\\pagefile.sys", volumeInfo->bitMap_Protect);
  32.     // 休眠文件
  33.     setBitmapDirectRWFile(volumeInfo->volume, L"\\hiberfil.sys", volumeInfo->bitMap_Protect);
  34. }
复制代码

下面这个函数很关键,写的不好,直接影响还原状态时的磁盘读写速度
  1. ULONGLONG
  2. DPBitMap_FindNext(DP_BITMAP * bitMap, ULONGLONG startIndex, BOOL set)
  3. {
  4.     LONG    jmpValue = set ? 0 : 0xFFFFFFFF;
  5.     ULONG    slot = 0;
  6.    
  7.     // 遍历slot
  8.     for (slot = startIndex / bitMap->regionSize; slot < bitMap->regionNumber; slot++)
  9.     {
  10.         ULONGLONG    max = 0;
  11.         
  12.         // 还没有分配
  13.         if (!bitMap->buffer[slot])
  14.         {
  15.             if (set)
  16.             {
  17.                 startIndex = (slot + 1) * bitMap->regionSize;
  18.                 continue;
  19.             }
  20.             else
  21.             {
  22.                 return startIndex;
  23.             }
  24.         }
  25.         // 便历块
  26.         for (max = min((slot + 1) * bitMap->regionSize, bitMap->bitMapSize);
  27.         startIndex < max; )
  28.         {
  29.             ULONG    sIndex = startIndex % bitMap->regionSize;
  30.             // 查找下一个置位的索引
  31.             if (jmpValue == ((PULONG)bitMap->buffer[slot])[sIndex / 32])
  32.             {
  33.                 // 快速跳越
  34.                 startIndex += 32 - (sIndex % 32);
  35.                 continue;
  36.             }
  37.             
  38.             if (set == ((((PULONG)bitMap->buffer[slot])[sIndex / 32] & (1 << (sIndex % 32))) > 0))
  39.             {
  40.                 // 找到
  41.                 return startIndex;
  42.             }   
  43.             startIndex++;
  44.         }
  45.     }
  46.    
  47.     return -1;
  48. }
  49. // 获取真实需要处理的簇
  50. ULONGLONG
  51. getRealSectorForRead(PVOLUME_INFO volumeInfo, ULONGLONG orgIndex)
  52. {
  53.     ULONGLONG    mapIndex = orgIndex;
  54.     // 此簇是否允许直接操作
  55.     if (isSectorProtect(volumeInfo, orgIndex))
  56.     {
  57.         return orgIndex;
  58.     }
  59.     // 此簇是否已经被重定向
  60.     if (DPBitMap_Test(volumeInfo->bitMap_Redirect, orgIndex))
  61.     {
  62.         // 找到重定向到哪里, 并返回   
  63.         PAIR *    result;
  64.         PAIR    pair;
  65.         pair.orgIndex = orgIndex;
  66.         result = (PAIR *)RtlLookupElementGenericTable(&volumeInfo->redirectMap, &pair);
  67.         if (result)
  68.         {
  69.             mapIndex = result->mapIndex;
  70.         }
  71.     }
  72.    
  73.     return mapIndex;
  74. }
  75. // 获取真实需要处理的簇
  76. ULONGLONG
  77. getRealSectorForWrite(PVOLUME_INFO volumeInfo, ULONGLONG orgIndex)
  78. {
  79.     ULONGLONG    mapIndex = -1;
  80.     // 此扇区是否允许直接写
  81.     if (isSectorProtect(volumeInfo, orgIndex))
  82.     {
  83.         return orgIndex;
  84.     }
  85.     // 此簇是否已经被重定向
  86.     if (DPBitMap_Test(volumeInfo->bitMap_Redirect, orgIndex))
  87.     {
  88.         // 找到重定向到哪里, 并返回   
  89.         PAIR *    result;
  90.         PAIR    pair;
  91.         pair.orgIndex = orgIndex;
  92.         
  93.         result = (PAIR *)RtlLookupElementGenericTable(&volumeInfo->redirectMap, &pair);
  94.         
  95.         if (result)
  96.         {
  97.             mapIndex = result->mapIndex;
  98.         }
  99.     }
  100.     else
  101.     {
  102.         // 查找下一个可用的空闲扇区
  103.         mapIndex = DPBitMap_FindNext(volumeInfo->bitMap_Free, volumeInfo->last_scan_index, FALSE);
  104.         if (mapIndex != -1)
  105.         {
  106.             // lastScan = 当前用到的 + 1
  107.             volumeInfo->last_scan_index = mapIndex + 1;
  108.             // 标记为非空闲
  109.             DPBitMap_Set(volumeInfo->bitMap_Free, mapIndex, TRUE);
  110.             
  111.             // 标记此扇区已被重定向(orgIndex)
  112.             DPBitMap_Set(volumeInfo->bitMap_Redirect, orgIndex, TRUE);
  113.             
  114.             // 加入重定向列表
  115.             {
  116.                 PAIR    pair;
  117.                 pair.orgIndex = orgIndex;
  118.                 pair.mapIndex = mapIndex;               
  119.                 RtlInsertElementGenericTable(&volumeInfo->redirectMap, &pair, sizeof(PAIR), NULL);
  120.             }
  121.         }
  122.     }
  123.     return mapIndex;
  124. }
复制代码

下面这个函数,整个磁盘还原的核心代码, 细看。
  1. // 模拟直接读写
  2. NTSTATUS
  3. handle_disk_request(
  4.     PVOLUME_INFO volumeInfo,
  5.     ULONG majorFunction,
  6.     ULONGLONG logicOffset,  
  7.     void * buff,
  8.     ULONG length)
  9. {
  10.     NTSTATUS    status;
  11.    
  12.     // 当前操作的物理偏移
  13.     ULONGLONG    physicalOffset = 0;
  14.     ULONGLONG    sectorIndex;
  15.     ULONGLONG    realIndex;
  16.     ULONG        bytesPerSector = volumeInfo->bytesPerSector;
  17.    
  18.     // 以下几个参数为判断为处理的簇是连续的簇而设
  19.     BOOLEAN        isFirstBlock = TRUE;
  20.     ULONGLONG    prevIndex = -1;
  21.     ULONGLONG    prevOffset = -1;
  22.     PVOID        prevBuffer = NULL;
  23.     ULONG        totalProcessBytes = 0;
  24.     // 判断上次要处理的簇跟这次要处理的簇是否连续,连续了就一起处理,否则单独处理, 加快速度
  25.     while (length)
  26.     {
  27.         sectorIndex = logicOffset / bytesPerSector;   
  28.         
  29.         if (IRP_MJ_READ == majorFunction)
  30.         {
  31.             realIndex = getRealSectorForRead(volumeInfo, sectorIndex);
  32.         }
  33.         else
  34.         {
  35.             // 传入后两个参数判断是否复制原簇数据
  36.             realIndex = getRealSectorForWrite(volumeInfo, sectorIndex);
  37.         }
  38.         
  39.         // 哥不是吧,硬盘太几巴小了, 老子不干了
  40.         if (-1 == realIndex)
  41.         {
  42.             dprintf("no enough disk space\n");
  43.             return STATUS_DISK_FULL;
  44.         }
  45.         
  46.         physicalOffset = realIndex * bytesPerSector;
  47. __reInit:        
  48.         // 初始prevIndex
  49.         if (isFirstBlock)
  50.         {
  51.             prevIndex = realIndex;
  52.             prevOffset = physicalOffset;
  53.             prevBuffer = buff;
  54.             totalProcessBytes = bytesPerSector;
  55.             
  56.             isFirstBlock = FALSE;
  57.             
  58.             goto __next;
  59.         }
  60.         
  61.         // 测试是否连继,  如果连续,跳到下个判断
  62.         if (prevIndex == (realIndex - 1))
  63.         {
  64.             prevIndex = realIndex;
  65.             totalProcessBytes += bytesPerSector;
  66.             goto __next;
  67.         }
  68.         // 处理上次连续需要处理的簇, 重置isFirstBlock
  69.         else
  70.         {
  71.             isFirstBlock = TRUE;
  72.             status = fastFsdRequest(volumeInfo->LowerDevObj, majorFunction, volumeInfo->physicalStartingOffset + prevOffset,
  73.                 prevBuffer, totalProcessBytes, TRUE);
  74.             // 重新初始化
  75.             goto __reInit;
  76.         }
  77. __next:        
  78.         // 最后一簇。。也就是完成了已经
  79.         if (bytesPerSector >= length)
  80.         {
  81.             status = fastFsdRequest(volumeInfo->LowerDevObj, majorFunction, volumeInfo->physicalStartingOffset + prevOffset,
  82.                 prevBuffer, totalProcessBytes, TRUE);
  83.             // 中断退出
  84.             break;
  85.         }
  86.         
  87.         // 跳到下一簇, 处理剩余的数据
  88.         logicOffset += (ULONGLONG)bytesPerSector;
  89.         buff = (char *)buff + bytesPerSector;
  90.         length -= bytesPerSector;
  91.     }
  92.    
  93.     return status;
  94. }
复制代码


磁盘读写的,注意vista以上的系统SL_FORCE_DIRECT_WRITE 的标志就行了
  1. NTSTATUS
  2. fastFsdRequest(
  3.     IN PDEVICE_OBJECT DeviceObject,
  4.     ULONG majorFunction,
  5.     IN LONGLONG ByteOffset,
  6.     OUT PVOID Buffer,
  7.     IN ULONG Length,               
  8.     IN BOOLEAN Wait
  9.     )
  10. {
  11.     PIRP                irp;
  12.     IO_STATUS_BLOCK        iosb;
  13.     KEVENT                event;
  14.     NTSTATUS            status;
  15.    
  16.     //
  17.     irp = IoBuildAsynchronousFsdRequest(majorFunction, DeviceObject,
  18.         Buffer, Length, (PLARGE_INTEGER) &ByteOffset, &iosb);
  19.     if (!irp) {
  20.         return STATUS_INSUFFICIENT_RESOURCES;
  21.     }
  22.     // vista 对直接磁盘写入进行了保护, 驱动操作需要在IRP的FLAGS加上SL_FORCE_DIRECT_WRITE标志
  23.     /*
  24.     If the SL_FORCE_DIRECT_WRITE flag is set, kernel-mode drivers can write to volume areas that they
  25.     normally cannot write to because of direct write blocking. Direct write blocking was implemented for
  26.     security reasons in Windows Vista and later operating systems. This flag is checked both at the file
  27.     system layer and storage stack layer. For more
  28.     information about direct write blocking, see Blocking Direct Write Operations to Volumes and Disks.
  29.     The SL_FORCE_DIRECT_WRITE flag is available in Windows Vista and later versions of Windows.
  30.     [url]http://msdn.microsoft.com/en-us/library/ms795960.aspx[/url]
  31.     */
  32.     if (IRP_MJ_WRITE == majorFunction)
  33.     {
  34.         IoGetNextIrpStackLocation(irp)->Flags |= SL_FORCE_DIRECT_WRITE;
  35.     }
  36.    
  37.     if (Wait) {
  38.         KeInitializeEvent(&event, NotificationEvent, FALSE);
  39.         IoSetCompletionRoutine(irp, FltReadWriteSectorsCompletion,
  40.             &event, TRUE, TRUE, TRUE);
  41.    
  42.         status = IoCallDriver(DeviceObject, irp);
  43.         if (STATUS_PENDING == status) {
  44.             KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);
  45.             status = iosb.Status;
  46.         }
  47.     } else {
  48.         IoSetCompletionRoutine(irp, FltReadWriteSectorsCompletion,
  49.             NULL, TRUE, TRUE, TRUE);
  50.         irp->UserIosb = NULL;
  51.         status = IoCallDriver(DeviceObject, irp);
  52.     }
  53.    
  54.     if (!NT_SUCCESS(status))
  55.     {
  56.         dprintf("IoCallDriver 0x%x fail 0x%x\n", majorFunction, status);
  57.     }
  58.     return status;
  59. }
复制代码

其实这个代码还可以优化,比如回收线程,我没加上,想让驱动尽量减低与系统驱动的耦合度
如果想加上,可以Hook 下文件删除操作,分析下删除的文件,把这个文件占用的簇标记为空闲,就行了
  1. // 回收线程
  2. VOID
  3. flt_thread_reclaim (
  4.     IN PVOID Context
  5.     )
  6. {
  7.     ULONG    i = 0;
  8.     ULONG    timeout = getTickCount();
  9.     PFILTER_DEVICE_EXTENSION    device_extension = (PFILTER_DEVICE_EXTENSION)Context;
  10.     while (!device_extension->terminate_thread)
  11.     {
  12.         if ((getTickCount() - timeout) > (1000 * 60))
  13.         {
  14.             for (i = 0; i < _countof(_volumeList); i++)
  15.             {
  16.                 if (_volumeList[i].isProtect && _volumeList[i].isProtect && _volumeList[i].isDiskFull)
  17.                 {
  18.                     // 回收
  19.                     reclaimDiskSpace(&_volumeList[i]);
  20.                 }
  21.                
  22.             }
  23.             
  24.             timeout = getTickCount();
  25.         }
  26.     }
  27.     PsTerminateSystemThread(STATUS_SUCCESS);
  28. }
复制代码


到此为止,基本上没啥说的了,其实上单点的磁盘还原都是这原理,不管你是硬的还原卡,还是软的磁盘过滤,最终都要用到以上这些东西。
相信会写驱动的人,只要知道原理,加上有充分的时间来看资料,跟写代码,都能写出来优秀的磁盘还原程序。程序不是最终目的,关键
写的过程中学到的东西,能认识到自己的不足,总结经验,所以程序写出来了,如果不是商业的,我支持开源。
  1. H:\diskRestore\diskfilter>dir /s
  2. 驱动器 H 中的卷没有标签。
  3. 卷的序列号是 949B-BAA3
  4. H:\diskRestore\diskfilter 的目录
  5. 2010-03-19  09:56    <DIR>          .
  6. 2010-03-19  09:56    <DIR>          ..
  7. 2010-03-19  09:51    <DIR>          app
  8. 2010-03-19  09:51    <DIR>          Bin
  9. 2010-03-02  16:02              423 build.bat
  10. 2010-03-19  09:56          713,756 diskfilter.zip
  11. 2010-03-19  09:51    <DIR>          sys
  12.               2 个文件        714,179 字节
  13. H:\diskRestore\diskfilter\app 的目录
  14. 2010-03-19  09:51    <DIR>          .
  15. 2010-03-19  09:51    <DIR>          ..
  16. 2010-02-01  21:10            79,159 CoolControlsManager.cpp
  17. 2010-02-01  21:04            14,588 CoolControlsManager.h
  18. 2010-01-28  15:19            3,195 DiskfltInst.cpp
  19. 2010-03-02  09:25            5,019 DiskfltInst.dsp
  20. 2010-01-27  12:08              545 DiskfltInst.dsw
  21. 2010-01-27  12:08                18 DiskfltInst.h
  22. 2010-03-02  12:04            6,475 DiskfltInst.rc
  23. 2010-03-02  12:19            6,483 DiskfltInst.rc.ljp
  24. 2010-01-28  03:18            2,075 GetPassWordDlg.h
  25. 2010-02-01  21:31            1,727 LoginDlg.h
  26. 2010-03-02  16:06            25,852 maindlg.h
  27. 2009-11-01  10:53            11,779 md5.c
  28. 2009-11-01  00:46            3,607 md5.h
  29. 2009-12-04  00:17          106,301 ntdll.h
  30. 2003-06-19  18:23          301,770 ntdll.lib
  31. 2010-01-27  19:47    <DIR>          res
  32. 2010-01-28  06:06            1,237 resource.h
  33. 2010-01-28  01:46              290 stdafx.cpp
  34. 2010-02-01  21:28              943 stdafx.h
  35.               18 个文件        571,063 字节
  36. H:\diskRestore\diskfilter\app\res 的目录
  37. 2010-01-27  19:47    <DIR>          .
  38. 2010-01-27  19:47    <DIR>          ..
  39. 2010-01-28  03:23              830 DiskfltInst.exe.manifest
  40. 2010-01-26  11:41            29,926 DiskfltInst.ico
  41.               2 个文件        30,756 字节
  42. H:\diskRestore\diskfilter\Bin 的目录
  43. 2010-03-19  09:51    <DIR>          .
  44. 2010-03-19  09:51    <DIR>          ..
  45. 2010-03-19  09:51          108,032 Aod.exe
  46. 2009-09-27  17:04          283,648 upx.exe
  47.               2 个文件        391,680 字节
  48. H:\diskRestore\diskfilter\sys 的目录
  49. 2010-03-19  09:51    <DIR>          .
  50. 2010-03-19  09:51    <DIR>          ..
  51. 2010-02-23  11:49              869 breakin.c
  52. 2010-03-02  15:52            7,559 diskfilter.dsp
  53. 2010-01-15  11:20              315 diskfilter.dsw
  54. 2010-01-26  11:48            3,212 diskfilter.rc
  55. 2010-03-19  09:51            68,142 diskflt.c
  56. 2010-03-02  09:04            1,300 diskflt.h
  57. 2010-01-28  00:28            66,869 diskfltlib.c
  58. 2010-01-28  00:57              925 diskfltlib.h
  59. 2010-01-15  22:54            3,376 fatlbr.h
  60. 2009-12-03  15:02            7,993 GenericTable.h
  61. 2010-01-18  22:15            1,246 log.c
  62. 2010-01-18  21:56              235 log.h
  63. 2009-11-01  10:53            11,779 md5.c
  64. 2009-11-01  00:46            3,607 md5.h
  65. 2010-03-01  10:51    <DIR>          mempool
  66. 2009-12-03  15:17          283,238 ntifs.h
  67. 2009-01-24  16:23            3,881 ntimage.h
  68. 2010-01-13  19:02            1,044 readme.txt
  69. 2010-01-26  11:52    <DIR>          res
  70. 2010-01-26  11:48              547 resource.h
  71.               18 个文件        466,137 字节
  72. H:\diskRestore\diskfilter\sys\mempool 的目录
  73. 2010-03-01  10:51    <DIR>          .
  74. 2010-03-01  10:51    <DIR>          ..
  75. 2005-09-26  10:22            2,950 debug.c
  76. 2009-04-27  02:49            2,515 debug.h
  77. 2010-03-01  10:51          184,692 malloc.c
  78. 2009-05-14  11:48            19,834 malloc.h
  79. 2010-01-25  19:57            4,101 mempool.c
  80. 2009-11-20  12:43            1,139 mempool.h
  81.               6 个文件        215,231 字节
  82. H:\diskRestore\diskfilter\sys\res 的目录
  83. 2010-01-26  11:52    <DIR>          .
  84. 2010-01-26  11:52    <DIR>          ..
  85. 2010-01-26  11:41            29,926 disk.ico
  86. 2010-01-26  11:48            28,902 disk1.ico
  87. 2010-01-22  12:40            29,926 disk_5.ico
  88. 2010-01-26  11:18            26,694 disk_6.ico
  89. 2010-01-26  11:29            25,214 shell32 239.ico
  90.               5 个文件        140,662 字节
  91.     所列文件总数:
  92.               53 个文件      2,529,708 字节
  93.               20 个目录 13,904,281,600 可用字节
复制代码

diskflt.zip (422 KB, 下载次数: 1770)
diskflt.jpg

Rank: 2

发表于 2010-3-19 12:42:52 |显示全部楼层
有码就顶!!!

Rank: 1

发表于 2010-3-19 12:49:07 |显示全部楼层
很好,很强大,很无私,很快就要多许多山寨产品了

Rank: 1

发表于 2010-3-19 12:51:05 |显示全部楼层
支持有码
必须骑兵

Rank: 1

发表于 2010-3-19 12:51:42 |显示全部楼层
支持楼主共享, 感谢, 研究下!

Rank: 1

发表于 2010-3-19 12:52:02 |显示全部楼层
不错,下载留名

Rank: 1

发表于 2010-3-19 12:55:14 |显示全部楼层
嗯 感谢 向作者致敬......

Rank: 1

发表于 2010-3-19 12:55:52 |显示全部楼层
强大着呢!!

Rank: 1

发表于 2010-3-19 12:56:39 |显示全部楼层
强烈建议 斑竹 加精 加声望 给予支持

Rank: 1

发表于 2010-3-19 12:59:52 |显示全部楼层
好东西·!下载学习!

Rank: 2

发表于 2010-3-19 13:01:49 |显示全部楼层
不看白不看,看看先

Rank: 1

发表于 2010-3-19 13:03:44 |显示全部楼层
顶一个呀

Rank: 1

发表于 2010-3-19 13:05:20 |显示全部楼层
支持分享。

Rank: 2

发表于 2010-3-19 13:08:41 |显示全部楼层
注释太详细了,膜拜

Rank: 1

发表于 2010-3-19 13:09:33 |显示全部楼层
支持楼主共享, 研究下!

Rank: 5Rank: 5

发表于 2010-3-19 13:14:03 |显示全部楼层
声望++
算法写的不错~

Rank: 1

发表于 2010-3-19 13:16:55 |显示全部楼层
这个好,这个相当不错,谢谢了

Rank: 1

发表于 2010-3-19 13:21:36 |显示全部楼层
专程来顶

Rank: 1

发表于 2010-3-19 13:23:50 |显示全部楼层
支持一下,看了,还不错

Rank: 1

发表于 2010-3-19 14:00:02 |显示全部楼层
非常感谢楼主的辛勤劳动,严重致敬!
您需要登录后才可以回帖 登录 | 立即加入

Archiver|手机版|第8个男人 - 论坛为只读模式,仅供查阅

GMT+8, 2019-7-22 08:20 , Processed in 0.044006 second(s), 11 queries .

Design by pvo.cn

© 2011 Pvo Inc.

回顶部