boywhp
驱动中牛
驱动中牛
  • 注册日期2007-08-09
  • 最后登录2015-04-24
  • 粉丝2
  • 关注0
  • 积分1105分
  • 威望515点
  • 贡献值0点
  • 好评度254点
  • 原创分1分
  • 专家分0分
阅读:8549回复:55

终于搞定了文件隐藏, 忙活了一个星期~哇哈哈

楼主#
更多 发布于:2007-08-27 16:59
测试win2KSP4基本正常,参考了FileMon的代码,其实驱动开发主要就是资料少,其它方面没有难度,无非就是按照MS设定好的套路写代码,写那个FASTIO的时候尤其是体力活啊,google才是最好的老师,论坛我问的问题没有任何人提醒我,也许是不屑于回答吧,但是对于一个新手来说,一个简单的问题也可以耗费好大量时间,需源码的新手Email我,我也才学一个多星期而已;-)

【环境搭设】
驱动开发一定要有一个调试环境,我是使用VMWare+共享文件夹+SoftICE+DebugView,在主机里面编译,然后切换到VM执行测试,再也不怕BSOD:-)
【变量声明】驱动程序在函数中声明变量,必须将所有的变量声明放函数开始的地方
【分配和释放字符串缓冲区】
RtlInitAnsiString函数初始化ANSI_STRING字符串。
RtlInitUnicodeString函数初始化UNICODE_STRING字符串。
RtlAnsiStringToUnicodeString函数把ANSI_STRING转化成UNICODE_STRING。
RtlFreeUnicodeString函数释放给字符串动态分配的内存。

RtlInitAnsiString和RtlInitUnicodeString初始化时不分配内存。不能使用RtlFreeUnicodeString函数。ANSI_STRING和UNICODE_STRING中的Buffer指向一个字符串常量,当调用RtlFreeUnicodeString时字符串常量占用的地址被释放。所以产生错误。
RtlAnsiStringToUnicodeString该函数被调用时,将为目标变量分配内存。所以在不使用该变量时要用该函数释放内存,以免内存泄漏。

例:
UNICODE_STRING string_unicode;
ANSI_STRING   string_ansi;
RtlInitUnicodeString(&string_unicode,L”Hello World!”);//不用释放内存
RtlInitAnsiString(&string_ansi,”Hello World!”);
RtlAnsiStringToUnicodeString(&string_unicode,&string_ansi,TRUE);//需要释放内存。
RtlFreeUnicodeString(&string_unicode);//释放动态分配的内存。

【DbgPrint 字符输出格式】
For DbgPrint (or macro KdPrint) - which is like printf - the following
formats should be used (expected type of argument):

1. %s    (PCHAR)
2. %ws    (PWCHAR)
3. %Z    (PSTRING, PANSI_STRING, POEM_STRING)
4. %wZ    (PUNICODE_STRING)

In fact %Z and %wZ are not documented in the official documentation,
but you can find them in CRT source file for _output().
【fastIO】
注意:一定要填写好FastIO函数,否则容易出问题
【DriverUnload】
注意:要首先使用IoDetachDevice卸载附在Device设备上的过滤设备,否则会导致BSOD

代码如下:
#include <ntddk.h>
#include "fastIO.h"
#include "test.h"

/*
 *    驱动主入口函数
 */
NTSTATUS
DriverEntry(
    IN PDRIVER_OBJECT DriverObject,
    IN PUNICODE_STRING RegistryPath)
{
    int i;
    NTSTATUS status;
    UNICODE_STRING nameString;
    PDEVICE_OBJECT FilterDevice;
    //首先创建一个CDO
    RtlInitUnicodeString(&nameString, L"\\FileSystem\\SFilter");
    status = IoCreateDevice(
                            DriverObject,
                            0,
                            &nameString,
                            FILE_DEVICE_DISK_FILE_SYSTEM,
                            FILE_DEVICE_SECURE_OPEN,
                            FALSE,
                            &g_CDO    
                            );
    if (!NT_SUCCESS(status))
    {
        KdPrint(("DriverEntry:Error Create cdo, status = %08x\n", status));
        return status;
    }
    //安装分发函数
    for (i=0; i<=IRP_MJ_MAXIMUM_FUNCTION; i++)
    {
        DriverObject->MajorFunction = SfPassThrough;
    }
    DriverObject->MajorFunction[IRP_MJ_DIRECTORY_CONTROL] = FsDirectoryControl;    
    DriverObject->DriverUnload = DriverUnload;
    //Fast IO
    InitFastIo(DriverObject);
    //准备绑定C:\的设备
    RtlInitUnicodeString(&nameString, L"\\DosDevices\\C:\\");
    if (!AttachToDiskDevice(&nameString, &FilterDevice))
    {
        KdPrint(("DrierEntry Failed..\n"));
        IoDeleteDevice(FilterDevice);
        return STATUS_DEVICE_CONFIGURATION_ERROR;
    }

    return status;//STATUS_DEVICE_CONFIGURATION_ERROR;
}

/*
 *驱动卸载    
 */
VOID
DriverUnload(IN PDRIVER_OBJECT DriverObject)
{
    //卸载资源
    PDEVICE_OBJECT DO = DriverObject->DeviceObject;
    PDEVICE_OBJECT NextDO = NULL;
    PDEVICE_EXTENSION DevEx = NULL;

    if (DriverObject)
    {
        while(DO)
        {
            KdPrint (("Unload Device...\n"));
            NextDO = DO->NextDevice;
            DevEx = DO->DeviceExtension;
            if (DevEx)
            {
                if (DevEx->AttachedToDevice)
                {
                    IoDetachDevice(DevEx->AttachedToDevice);
                }
            }
            IoDeleteDevice(DO);
            DO = NextDO;
        }
    }
    //释放FastIo
    DestoryFastIo(DriverObject);
}

/*
 *    驱动的目录处理函数
 */
NTSTATUS
FsDirectoryControl(IN PDEVICE_OBJECT DeviceObject,
                   IN PIRP Irp)
{
    NTSTATUS status;
    PIO_STACK_LOCATION irpSp = IoGetCurrentIrpStackLocation(Irp);    //当前Irp(IO_STACK_LOCATION)的参数
    PDEVICE_EXTENSION devExt = DeviceObject->DeviceExtension;
    PFILE_BOTH_DIR_INFORMATION dirInfo = NULL;
    KEVENT waitEvent;
    //UNICODE_STRING path;

    ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
    if (IRP_MN_QUERY_DIRECTORY != irpSp->MinorFunction)
    {
        goto SkipHandle;
    }
    if (Irp->RequestorMode == KernelMode)
    {
        goto SkipHandle;
    }
    if (FileBothDirectoryInformation != ((PQUERY_DIRECTORY)&irpSp->Parameters)->FileInformationClass)
    {    
        goto SkipHandle;
    }
    //设置完成回调函数
    KeInitializeEvent(&waitEvent, NotificationEvent, FALSE);
    IoCopyCurrentIrpStackLocationToNext(Irp);
    //IoSetCompletionRoutine(Irp,CompletionRoutine,context,InvokeOnSuccess,InvokeOnError,InvokeOnCancel);
    IoSetCompletionRoutine(    
                            Irp,
                            DirControlCompletion,        //CompletionRoutine
                            &waitEvent,                    //context parameter
                            TRUE,
                            TRUE,
                            TRUE
                            );

    status = IoCallDriver(devExt->AttachedToDevice, Irp);
    if (STATUS_PENDING == status)
    {
        //等待完成
        status = KeWaitForSingleObject(&waitEvent,
                                        Executive,
                                        KernelMode,
                                        FALSE,
                                        NULL
                                        );
        ASSERT(STATUS_SUCCESS == status);
    }
    if (!NT_SUCCESS(status) ||(0 == irpSp->Parameters.QueryFile.Length))
    {    
        IoCompleteRequest(Irp, IO_NO_INCREMENT);
        return status;
    }
    //KdPrint(("Hook Directory.\n"));
    HandleDirectory(Irp->UserBuffer,  &((PQUERY_DIRECTORY)&irpSp->Parameters)->Length);
    IoCompleteRequest(Irp, IO_NO_INCREMENT);
    return status;

SkipHandle:
    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(devExt->AttachedToDevice, Irp);
}

BOOLEAN
HandleDirectory(IN OUT PFILE_BOTH_DIR_INFORMATION DirInfo, IN PULONG lpBufLenth)
{
    //处理目录操作
    PFILE_BOTH_DIR_INFORMATION currentDirInfo = DirInfo;
    ULONG offset = 0;
    ULONG position = 0;
    ULONG newLenth = *lpBufLenth;
    WCHAR fileName[] = L"HideTest.txt";
    do
    {
        offset = currentDirInfo->NextEntryOffset;

        if (!(FILE_ATTRIBUTE_DIRECTORY & currentDirInfo->FileAttributes) &&
            (0 == wcsncmp(currentDirInfo->FileName, fileName, currentDirInfo->FileNameLength>>1)))
        {
            //Now We Will Test The FileName
            //KdPrint(("%08x Hided File:%ws[%d]\n", currentDirInfo->FileAttributes, currentDirInfo->FileName, currentDirInfo->FileNameLength));
            RtlMoveMemory(currentDirInfo, (PUCHAR)currentDirInfo + offset, *lpBufLenth - position - offset);
            newLenth -= offset;
            position += offset;
        }
        else
        {
            //KdPrint(("%08x Directory:%ws\n", currentDirInfo->FileAttributes, currentDirInfo->FileName));
            //Move Next
            position += offset;
            currentDirInfo = (PFILE_BOTH_DIR_INFORMATION)((PUCHAR)currentDirInfo + offset);
        }
    } while (0 != offset);
    *lpBufLenth = newLenth;
    return TRUE;
}

BOOLEAN
CmpWString(const WCHAR *s1, const WCHAR *s2, ULONG size)
{
    return TRUE;
}

NTSTATUS
DirControlCompletion(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp, IN PVOID Context)
{
    //if (Irp->PendingReturned) IoMarkIrpPending(Irp);
    KeSetEvent((PKEVENT)Context, IO_NO_INCREMENT, FALSE);
    return STATUS_MORE_PROCESSING_REQUIRED;    //注:必须返回这个值
}
BOOLEAN
IS_MY_DEVICE_OBJECT(PDEVICE_OBJECT DeviceObject)
{
    return DeviceObject->DriverObject == g_CDO->DriverObject;
}

/*
 *     挂载到指定的磁盘设备
 */
BOOLEAN
AttachToDiskDevice(IN PUNICODE_STRING pDiskName, OUT PDEVICE_OBJECT *pOurDevice)
{
    NTSTATUS status;
    PDEVICE_EXTENSION DevEx;
    PDEVICE_OBJECT DiskDeviceObject;
    PDEVICE_OBJECT NewDeviceObject;

    IO_STATUS_BLOCK ioStatus;
    OBJECT_ATTRIBUTES objectAttributes;
    PFILE_OBJECT fileObject = NULL;
    HANDLE ntFileHandle;
    // We have to figure out what device to hook - first open the volume's
    // root directory
    //
    InitializeObjectAttributes(&objectAttributes, pDiskName, OBJ_CASE_INSENSITIVE, NULL, NULL );
    status = ZwCreateFile(&ntFileHandle, SYNCHRONIZE|FILE_ANY_ACCESS,
                            &objectAttributes, &ioStatus, NULL, 0,
                            FILE_SHARE_READ|FILE_SHARE_WRITE,
                            FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE,
                            NULL, 0);

    if (!NT_SUCCESS(status))
    {
        DbgPrint(("Filemon: Could not open drive\n"));
        return FALSE;
    }
    KdPrint(("Open Device is OK\n"));
    //
    // Got the file handle, so now look-up the file-object it refers to
    //
    status = ObReferenceObjectByHandle(ntFileHandle, FILE_READ_DATA, NULL, KernelMode, &fileObject, NULL);
    if(!NT_SUCCESS(status))
    {
        DbgPrint(("Filemon: Could not get fileobject from handle\n"));
        ZwClose(ntFileHandle);
        return FALSE;            
    }
    DiskDeviceObject = IoGetRelatedDeviceObject(fileObject);
    if(!DiskDeviceObject)
    {
        DbgPrint(("Filemon: Could not get related device object\n"));
        goto ErrHand;
    }
    //创建挂载设备
    status = IoCreateDevice(
                            g_CDO->DriverObject,
                            sizeof(DEVICE_EXTENSION),
                            NULL,
                            DiskDeviceObject->DeviceType,
                            FILE_DEVICE_SECURE_OPEN,
                            FALSE,
                            &NewDeviceObject
                            );
    if (!NT_SUCCESS(status))
    {
        goto ErrHand;
    }
    NewDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;
    *pOurDevice = NewDeviceObject;

    DevEx = NewDeviceObject->DeviceExtension;
    DevEx->AttachedToDevice = DiskDeviceObject;
    DevEx->DeviceName.Length = 0;
    DevEx->DeviceName.MaximumLength = sizeof(DevEx->DeviceNameBuffer);
    DevEx->DeviceName.Buffer = DevEx->DeviceNameBuffer;
    //RtlFillMemory(DevEx->DeviceName.Buffer, sizeof(DevEx->DeviceNameBuffer), 0);
    SfGetObjectName(g_CDO, &(DevEx->DeviceName));

    //执行挂载
    DevEx->AttachedToDevice = IoAttachDeviceToDeviceStack(NewDeviceObject, DiskDeviceObject);
    if (!DevEx->AttachedToDevice)
    {
        goto ErrHand;
    }

    KdPrint(("Attath Device is OK\n"));
    ObDereferenceObject(fileObject);
    ZwClose(ntFileHandle);
    return TRUE;

ErrHand:
    KdPrint(("AttachDevice Failed status %08x\n", status));
    ObDereferenceObject(fileObject);
    ZwClose(ntFileHandle);
    return  FALSE;
}


/*
 *    不处理的Irp
 */
NTSTATUS
SfPassThrough(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
    //不处理
    ASSERT(IS_MY_DEVICE_OBJECT(DeviceObject));
    IoSkipCurrentIrpStackLocation(Irp);
    return IoCallDriver(((PDEVICE_EXTENSION)DeviceObject->DeviceExtension)->AttachedToDevice, Irp);
}

/*
 *    得到一个对象的名称
 */
VOID
SfGetObjectName(
    IN PVOID Object,
    IN OUT PUNICODE_STRING Name
)
{
    NTSTATUS status;
    CHAR nibuf[512]; //buffer that receives NAME information and name

    POBJECT_NAME_INFORMATION nameInfo = (POBJECT_NAME_INFORMATION)nibuf;
    ULONG retLength;
    
    status = ObQueryNameString(Object, nameInfo, sizeof(nibuf), &retLength);
    
    Name->Length = 0;
    if (NT_SUCCESS( status ))
    {
        RtlCopyUnicodeString(Name, &nameInfo->Name);
        //KdPrint(("Object %wZ,Len = %d.[%d]\n", Name, retLength, Name->Length));
    }
}
sas
sas
驱动牛犊
驱动牛犊
  • 注册日期2008-06-14
  • 最后登录2008-07-29
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2008-06-14 20:53
怎么实现文件重定向,比如访问 d:\aa\33.dll 变成 e:\bb\44.dll,有源码学习吗,goyanjie@21cn.com
sas
sas
驱动牛犊
驱动牛犊
  • 注册日期2008-06-14
  • 最后登录2008-07-29
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望3点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2008-06-14 20:48
我想知道怎么文件重定向,比如访问d:\aa\33.dll 变成e:\bb\44.dll,有源码学习最好,goyanjie@21cn.com
mr6698
驱动牛犊
驱动牛犊
  • 注册日期2008-03-26
  • 最后登录2017-09-27
  • 粉丝3
  • 关注0
  • 积分21分
  • 威望200点
  • 贡献值0点
  • 好评度26点
  • 原创分0分
  • 专家分1分
地板#
发布于:2008-04-30 13:30
目前还没碰到这个问题
不过楼主的共享精神 超赞!
dj04061340
驱动牛犊
驱动牛犊
  • 注册日期2008-04-21
  • 最后登录2008-04-22
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望2点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
地下室#
发布于:2008-04-21 11:02
楼主可以给我发一份源码么,最近刚刚开始学这个,感觉一塌糊涂,china.jiangdong@163.com
wenyurs
驱动牛犊
驱动牛犊
  • 注册日期2006-02-15
  • 最后登录2011-02-25
  • 粉丝2
  • 关注0
  • 积分190分
  • 威望128点
  • 贡献值0点
  • 好评度17点
  • 原创分0分
  • 专家分0分
5楼#
发布于:2007-12-25 10:26
楼主 能给我一份你的代码 本人正在学习中 谢谢
zhou_huawen@hotmail.com
wengzuhong
驱动小牛
驱动小牛
  • 注册日期2004-07-16
  • 最后登录2014-10-22
  • 粉丝3
  • 关注1
  • 积分9分
  • 威望262点
  • 贡献值0点
  • 好评度219点
  • 原创分0分
  • 专家分0分
6楼#
发布于:2007-12-18 16:13
fancylf ,我也是用了虚的隐藏,不过会有问题的
Pegram
论坛版主
论坛版主
  • 注册日期2005-12-03
  • 最后登录2013-08-23
  • 粉丝13
  • 关注5
  • 积分1333分
  • 威望4717点
  • 贡献值1点
  • 好评度78点
  • 原创分0分
  • 专家分2分
7楼#
发布于:2007-12-17 15:48
BOOLEAN Attach2C_Volume()
{
   UNICODE_STRING nameString;
   PDEVICE_OBJECT VolumeDeviceObject;
   PFILE_OBJECT fileObject;
   NTSTATUS ntStatus;
   PSFILTER_DEVICE_EXTENSION sfExtention;

   PDEVICE_OBJECT     fileSysDevice;
   IO_STATUS_BLOCK   ioStatus;
   HANDLE         ntFileHandle;  
   OBJECT_ATTRIBUTES   objectAttributes;

   PAGED_CODE();
   RtlInitUnicodeString( &nameString, L"\\DosDevices\\C:\\" );

   InitializeObjectAttributes( &objectAttributes, &nameString,
       OBJ_CASE_INSENSITIVE, NULL, NULL );
   ntStatus = ZwCreateFile( &ntFileHandle, SYNCHRONIZE|FILE_ANY_ACCESS,
       &objectAttributes, &ioStatus, NULL, 0, FILE_SHARE_READ|FILE_SHARE_WRITE,
       FILE_OPEN,
       FILE_SYNCHRONOUS_IO_NONALERT|FILE_DIRECTORY_FILE,
       NULL, 0 );

   if( !NT_SUCCESS( ntStatus ) )
   {
       //DbgPrint(("Filemon: Could not open drive %c: \n", 'C'+0));
       return FALSE;
   }

   DbgPrint(("Filemon: opened the root directory!!! handle: %x\n", ntFileHandle));  

   ntStatus = ObReferenceObjectByHandle( ntFileHandle, FILE_READ_DATA,
       NULL, KernelMode, &fileObject, NULL );
   if( !NT_SUCCESS( ntStatus )) {
       ZwClose( ntFileHandle );
       return FALSE;
   }

   fileSysDevice = IoGetRelatedDeviceObject( fileObject );

   if( ! fileSysDevice ) {
       ObDereferenceObject( fileObject );
       ZwClose( ntFileHandle );
       return FALSE;
   }

   ntStatus = IoCreateDevice( gSFilterDriverObject,
       sizeof(SFILTER_DEVICE_EXTENSION),
       NULL,
       fileSysDevice->DeviceType,
       0,
       FALSE,
       &VolumeDeviceObject );
   if( !NT_SUCCESS(ntStatus) ) {
       ObDereferenceObject( fileObject );
       ZwClose( ntFileHandle );

       return FALSE;
   }

   VolumeDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING;

   sfExtention = VolumeDeviceObject->DeviceExtension;
   sfExtention->AttachedToDeviceObject = fileSysDevice;
   RtlInitUnicodeString(&sfExtention->DeviceName, sfExtention->DeviceNameBuffer);
   RtlCopyUnicodeString(&sfExtention->DeviceName, &nameString);

   ntStatus = IoAttachDeviceByPointer( VolumeDeviceObject, fileSysDevice );
   if( !NT_SUCCESS(ntStatus) )
   {
       ObDereferenceObject( fileObject );
       ZwClose( ntFileHandle );

       return FALSE;
   }

   ObDereferenceObject( fileObject );

   ZwClose( ntFileHandle );
   return TRUE;
}
《寒江独钓》与《竹林蹊径》的合作作者。精通USB开发,设计了CY001 USB驱动套件(http://bbs.driverdevelop.com/read.php?tid-119314.html)。
Pegram
论坛版主
论坛版主
  • 注册日期2005-12-03
  • 最后登录2013-08-23
  • 粉丝13
  • 关注5
  • 积分1333分
  • 威望4717点
  • 贡献值1点
  • 好评度78点
  • 原创分0分
  • 专家分2分
8楼#
发布于:2007-12-17 15:44
//准备绑定C:\的设备
    RtlInitUnicodeString(&nameString, L"\\DosDevices\\C:\\");
    if (!AttachToDiskDevice(&nameString, &FilterDevice))
这一段实现跟我发布的函数Attach2C_Volume很像。
《寒江独钓》与《竹林蹊径》的合作作者。精通USB开发,设计了CY001 USB驱动套件(http://bbs.driverdevelop.com/read.php?tid-119314.html)。
Pegram
论坛版主
论坛版主
  • 注册日期2005-12-03
  • 最后登录2013-08-23
  • 粉丝13
  • 关注5
  • 积分1333分
  • 威望4717点
  • 贡献值1点
  • 好评度78点
  • 原创分0分
  • 专家分2分
9楼#
发布于:2007-12-17 15:36
好啊。学习一下。
《寒江独钓》与《竹林蹊径》的合作作者。精通USB开发,设计了CY001 USB驱动套件(http://bbs.driverdevelop.com/read.php?tid-119314.html)。
th800114
驱动牛犊
驱动牛犊
  • 注册日期2007-10-01
  • 最后登录2011-03-23
  • 粉丝0
  • 关注0
  • 积分14分
  • 威望42点
  • 贡献值0点
  • 好评度1点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2007-11-05 08:32
boywhp
驱动中牛
驱动中牛
  • 注册日期2007-08-09
  • 最后登录2015-04-24
  • 粉丝2
  • 关注0
  • 积分1105分
  • 威望515点
  • 贡献值0点
  • 好评度254点
  • 原创分1分
  • 专家分0分
11楼#
发布于:2007-10-05 16:28
代码已经放出来了,我没想到还有这么多跟我一样的新人,呵呵!
http://bbs.driverdevelop.com/htm_data/39/0709/105273.html
forrich
驱动牛犊
驱动牛犊
  • 注册日期2007-09-11
  • 最后登录2010-02-09
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望3点
  • 贡献值0点
  • 好评度2点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2007-10-05 08:59
楼主,给我一份hoposky@163.com
谢谢了
HI
wanfustudio
驱动牛犊
驱动牛犊
  • 注册日期2006-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分720分
  • 威望73点
  • 贡献值0点
  • 好评度72点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2007-09-20 10:18
楼主认真,我最偷懒
直接在FileSpy上改了改
hyzimbtb
驱动牛犊
驱动牛犊
  • 注册日期2004-08-27
  • 最后登录2010-11-10
  • 粉丝2
  • 关注0
  • 积分387分
  • 威望216点
  • 贡献值0点
  • 好评度45点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2007-09-19 11:31
楼主,给我一份hyzimbtb@163.com
wanfustudio
驱动牛犊
驱动牛犊
  • 注册日期2006-08-09
  • 最后登录2016-01-09
  • 粉丝0
  • 关注0
  • 积分720分
  • 威望73点
  • 贡献值0点
  • 好评度72点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2007-09-19 10:17
呵呵,看得眼晕中
下回整个正着的哦

支持一下
tianzheng
驱动牛犊
驱动牛犊
  • 注册日期2005-11-01
  • 最后登录2009-10-22
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望10点
  • 贡献值0点
  • 好评度4点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2007-09-18 23:00
谢谢楼主。能给我发一份代码学习一下么?tianzhengmail@163.com
dfg
lkni
驱动牛犊
驱动牛犊
  • 注册日期2007-09-18
  • 最后登录2010-08-15
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望22点
  • 贡献值0点
  • 好评度21点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2007-09-18 10:54
学习谢谢分享
驱网无线,快乐无限
niklen
驱动牛犊
驱动牛犊
  • 注册日期2005-11-03
  • 最后登录2014-07-22
  • 粉丝0
  • 关注0
  • 积分0分
  • 威望20点
  • 贡献值0点
  • 好评度19点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2007-09-16 19:11
给一份研究下 谢谢
niklen@163.com
ProPlayboy
驱动大牛
驱动大牛
  • 注册日期2005-07-07
  • 最后登录2022-02-15
  • 粉丝0
  • 关注0
  • 积分1016分
  • 威望811点
  • 贡献值0点
  • 好评度719点
  • 原创分0分
  • 专家分0分
  • 社区居民
19楼#
发布于:2007-09-16 14:45
有些驱动,里面的逻辑和复杂度,变态到你难以想像。。。
人不靓仔心灵美,版头不正红花仔!
上一页
游客

返回顶部