hothua
驱动牛犊
驱动牛犊
  • 注册日期2006-06-20
  • 最后登录2009-11-17
  • 粉丝0
  • 关注0
  • 积分23分
  • 威望191点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分1分
阅读:20766回复:95

禁用和只读U盘驱动的实现

楼主#
更多 发布于:2009-10-02 23:15
我是把ddk中filter.c例子增加了IRP_MJ_SCSI例程,在 {36FC9E60-C465-11CF-8056-444553540000} 下增加了LowerFilters="usbstorfilter",然后在service下增加了usbstorfilter。
具体是在IRP_MJ_SCSI中实现禁用和主动添加对USBSTOR的过滤设备,具体实现见代码。经测试存在2个问题
(1)、本人基本功太差,程序中存在一些错误,比如好像存在分页和IRQLEVEL冲突造成系统蓝屏异常,所以将代码发上来请大家指点。
(2)、不能通过程序控制在不重启机器情况下控制U盘的使用。
USBFILTER.rar

最新喜欢:

hetaooshetaoo... x1234521x12345...
wyhero
驱动牛犊
驱动牛犊
  • 注册日期2008-03-17
  • 最后登录2016-02-02
  • 粉丝0
  • 关注0
  • 积分67分
  • 威望563点
  • 贡献值0点
  • 好评度17点
  • 原创分0分
  • 专家分0分
沙发#
发布于:2009-10-03 00:09
新手,学习一下
wyhero
驱动牛犊
驱动牛犊
  • 注册日期2008-03-17
  • 最后登录2016-02-02
  • 粉丝0
  • 关注0
  • 积分67分
  • 威望563点
  • 贡献值0点
  • 好评度17点
  • 原创分0分
  • 专家分0分
板凳#
发布于:2009-10-03 00:11
我已回复,为什么看不到?
hothua
驱动牛犊
驱动牛犊
  • 注册日期2006-06-20
  • 最后登录2009-11-17
  • 粉丝0
  • 关注0
  • 积分23分
  • 威望191点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分1分
地板#
发布于:2009-10-03 14:02
不太熟悉如何上传附件,我也没想设置附件隐藏,无线上网,传送附件不知道成不成功。
 
附件名称/大小 下载次数 最后更新
USBFILTER.rar (10KB)  156 2009-10-03 14:02
USBFILTER.rar (10KB)  175 2009-10-03 14:14
hothua
驱动牛犊
驱动牛犊
  • 注册日期2006-06-20
  • 最后登录2009-11-17
  • 粉丝0
  • 关注0
  • 积分23分
  • 威望191点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分1分
地下室#
发布于:2009-10-05 09:23
为了方便高手指点,现将代码直接贴出来,可能篇幅稍长,请版主原谅
头文件:
#if !defined(_FILTER_H_)  //注意这个位置不能乱放,我的认识是要放在加载的头文件的下面 
#define _FILTER_H_ 
#include <ntddk.h> 
#include <scsi.h> 
#include <wdmsec.h> // for IoCreateDeviceSecure 
#include <initguid.h> 
// {8E7341F9-04AD-41da-AC0E-72099E39D7EE} 
DEFINE_GUID(GUID_SD_FILTER_CONTROL_OBJECT, 
   0x8e7341f9, 0x4ad, 0x41da, 0xac, 0xe, 0x72, 0x9, 0x9e, 0x39, 0xd7, 0xee); 
#define IOCTL_820 \ 
    CTL_CODE(FILE_DEVICE_DISK, 0x820, METHOD_BUFFERED, FILE_ANY_ACCESS) 
#define DISK_TAG_SRB           'SDcS'  // "ScDS" - srb allocation 
#define MAXLEN 256 

#ifndef STATUS_CONTINUE_COMPLETION 
#define STATUS_CONTINUE_COMPLETION STATUS_SUCCESS 
#endif 
#define POOL_TAG 'liFT' 
typedef enum _DEVICE_PNP_STATE{ 
 NotStarted = 0, 
 Started, 
 StopPending, 
 Stopped, 
 RemovePending, 
 SurpriseRemovePending, 
 Deleted 
} DEVICE_PNP_STATE; 
#define INITIALIZE_PNP_STATE(_Data_)    \ 
 (_Data_)->DevicePnPState =  NotStarted;\ 
(_Data_)->PreviousPnPState = NotStarted; 
#define SET_NEW_PNP_STATE(_Data_, _state_) \ 
 (_Data_)->PreviousPnPState =  (_Data_)->DevicePnPState;\ 
(_Data_)->DevicePnPState = (_state_); 
#define RESTORE_PREVIOUS_PNP_STATE(_Data_)   \ 
        (_Data_)->DevicePnPState =   (_Data_)->PreviousPnPState;\ 
typedef struct _HUA_ATTACHED_DEVICE 
{ 
 LIST_ENTRY listEntry; 
 PDEVICE_OBJECT FilterUsbStor;  
 PDEVICE_OBJECT FilterUsbStorLowerDriver;  
}HUA_ATTACHED_DEVICE,*PHUA_ATTACHED_DEVICE; 
typedef struct _DEVICE_EXTENSION 
{ 
 // A back pointer to the device object. 
 PDEVICE_OBJECT Self; 
 //The top of the stack before this filter was added. 
 PDEVICE_OBJECT NextLowerDriver; 
 //Current PnP state of the device 
 DEVICE_PNP_STATE DevicePnPState; 
 //The previous pnp state 
 DEVICE_PNP_STATE  PreviousPnPState; 
 //Removelock to track IRPs so that device can be 
 //removed and the driver can be unloaded safely. 
 IO_REMOVE_LOCK  RemoveLock; 
 //HUA ADD 
 LIST_ENTRY pFilterUsbStorListHead;   
 USHORT bUSBSTORFILTERDEVICE; 
} DEVICE_EXTENSION,*PDEVICE_EXTENSION; 
NTSTATUS 
FilterAddDeviceFun( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PDEVICE_OBJECT PhysicalDeviceObject, 
 IN USHORT bUSBSTORFILTERDEVICE, 
 IN OUT PDEVICE_OBJECT  *deviceObject 
    ); 
NTSTATUS 
FilterAddDevice( 
 IN PDRIVER_OBJECT DriverObject, 
 IN PDEVICE_OBJECT PhysicalDeviceObject 
 ); 
NTSTATUS 
FilterDispatchPnp( 
 IN PDEVICE_OBJECT DeviceObject, 
 IN PIRP Irp 
 ); 
NTSTATUS 
FilterDispatchPower( 
     IN PDEVICE_OBJECT    DeviceObject, 
     IN PIRP              Irp 
    ); 
VOID 
FilterUnload( 
 IN PDRIVER_OBJECT DriverObject   
 ); 
NTSTATUS 
FilterPass( 
 IN PDEVICE_OBJECT DeviceObject, 
 IN PIRP Irp   
 ); 
NTSTATUS 
DriverEntry( 
 IN PDRIVER_OBJECT DriverObject, 
 IN PUNICODE_STRING RegistryPath 
 ); 
NTSTATUS 
FilterStartCompletionRoutine( 
 IN PDEVICE_OBJECT DeviceObject,       
 IN PIRP    Irp, 
 IN PVOID   Context 
 ); 
NTSTATUS 
FilterDeviceUsageNotificationCompletionRoutine( 
    IN PDEVICE_OBJECT   DeviceObject, 
    IN PIRP             Irp, 
    IN PVOID            Context 
    ); 
NTSTATUS 
FilterDispatchScsi( IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ); 
NTSTATUS 
USBSCSICompletion( IN PDEVICE_OBJECT DeviceObject, 
                            IN PIRP Irp, 
                            IN PVOID Context ); 
NTSTATUS 
USBSCSICompletion2( IN PDEVICE_OBJECT DeviceObject, 
      IN PIRP Irp, 
                            IN PVOID Context ); 
NTSTATUS 
CreateFilterUsbstoreObject(IN PDEVICE_OBJECT    DeviceObject, 
         IN PDEVICE_OBJECT    UsbStorDeviceObject 
         ); 
// 这个函数是事实存在的,只是文档中没有公开。声明一下 
// 就可以直接使用了。 
NTSTATUS 
ObReferenceObjectByName( 
                        PUNICODE_STRING ObjectName, 
                        ULONG Attributes, 
                        PACCESS_STATE AccessState, 
                        ACCESS_MASK DesiredAccess, 
                        POBJECT_TYPE ObjectType, 
                        KPROCESSOR_MODE AccessMode, 
                        PVOID ParseContext, 
                        PVOID *Object 
                        ); 
extern POBJECT_TYPE IoDriverObjectType; 
#define USB_STOR_DRIVER_NAME L"\\Driver\\USBSTOR" 
#define NTDEVICE_NAME_STRING      L"\\Device\\HUSBFilter" 
#define SYMBOLIC_NAME_STRING      L"\\DosDevices\\HUSBFilter" 
typedef struct _CONTROL_DEVICE_EXTENSION { 
  
    ULONG   Deleted; // False if the deviceobject is valid, TRUE if it's deleted 
    
    PVOID   ControlData; // Store your control data here 
    
} CONTROL_DEVICE_EXTENSION, *PCONTROL_DEVICE_EXTENSION; 
NTSTATUS 
FilterCreateControlObject( 
        IN PDEVICE_OBJECT    DeviceObject 
        ); 
VOID 
FilterDeleteControlObject( 
        ); 
NTSTATUS 
FilterDispatchIo( 
     IN PDEVICE_OBJECT    DeviceObject, 
     IN PIRP              Irp 
     ); 
#endif
hothua
驱动牛犊
驱动牛犊
  • 注册日期2006-06-20
  • 最后登录2009-11-17
  • 粉丝0
  • 关注0
  • 积分23分
  • 威望191点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分1分
5楼#
发布于:2009-10-05 09:24
实现代码:
#include "filter.h" 
#ifdef ALLOC_PRAGMA 
#pragma alloc_text (INIT, DriverEntry) 
#pragma alloc_text (PAGE, FilterAddDevice) 
#pragma alloc_text (PAGE, FilterDispatchPnp) 
#pragma alloc_text (PAGE, FilterUnload) 
#pragma alloc_text (PAGE, FilterCreateControlObject) 
#pragma alloc_text (PAGE, FilterDeleteControlObject) 
#pragma alloc_text (PAGE, FilterDispatchIo) 
#endif 
FAST_MUTEX ControlMutex; 
ULONG InstanceCount = 0; 
PDEVICE_OBJECT ControlDeviceObject; 
int   flag=2;//0:不控制;1:不可见;2:只读 
PDEVICE_OBJECT firstUsbStorDeviceObject=NULL; 
#if DBG 
PCHAR 
PnPMinorFunctionString ( 
      UCHAR MinorFunction 
      ) 
{ 
    switch (MinorFunction) 
    { 
 case IRP_MN_START_DEVICE: 
  return "IRP_MN_START_DEVICE"; 
 case IRP_MN_QUERY_REMOVE_DEVICE: 
  return "IRP_MN_QUERY_REMOVE_DEVICE"; 
 case IRP_MN_REMOVE_DEVICE: 
  return "IRP_MN_REMOVE_DEVICE"; 
 case IRP_MN_CANCEL_REMOVE_DEVICE: 
  return "IRP_MN_CANCEL_REMOVE_DEVICE"; 
 case IRP_MN_STOP_DEVICE: 
  return "IRP_MN_STOP_DEVICE"; 
 case IRP_MN_QUERY_STOP_DEVICE: 
  return "IRP_MN_QUERY_STOP_DEVICE"; 
 case IRP_MN_CANCEL_STOP_DEVICE: 
  return "IRP_MN_CANCEL_STOP_DEVICE"; 
 case IRP_MN_QUERY_DEVICE_RELATIONS: 
  return "IRP_MN_QUERY_DEVICE_RELATIONS"; 
 case IRP_MN_QUERY_INTERFACE: 
  return "IRP_MN_QUERY_INTERFACE"; 
 case IRP_MN_QUERY_CAPABILITIES: 
  return "IRP_MN_QUERY_CAPABILITIES"; 
 case IRP_MN_QUERY_RESOURCES: 
  return "IRP_MN_QUERY_RESOURCES"; 
 case IRP_MN_QUERY_RESOURCE_REQUIREMENTS: 
  return "IRP_MN_QUERY_RESOURCE_REQUIREMENTS"; 
 case IRP_MN_QUERY_DEVICE_TEXT: 
  return "IRP_MN_QUERY_DEVICE_TEXT"; 
 case IRP_MN_FILTER_RESOURCE_REQUIREMENTS: 
  return "IRP_MN_FILTER_RESOURCE_REQUIREMENTS"; 
 case IRP_MN_READ_CONFIG: 
  return "IRP_MN_READ_CONFIG"; 
 case IRP_MN_WRITE_CONFIG: 
  return "IRP_MN_WRITE_CONFIG"; 
 case IRP_MN_EJECT: 
  return "IRP_MN_EJECT"; 
 case IRP_MN_SET_LOCK: 
  return "IRP_MN_SET_LOCK"; 
 case IRP_MN_QUERY_ID: 
  return "IRP_MN_QUERY_ID"; 
 case IRP_MN_QUERY_PNP_DEVICE_STATE: 
  return "IRP_MN_QUERY_PNP_DEVICE_STATE"; 
 case IRP_MN_QUERY_BUS_INFORMATION: 
  return "IRP_MN_QUERY_BUS_INFORMATION"; 
 case IRP_MN_DEVICE_USAGE_NOTIFICATION: 
  return "IRP_MN_DEVICE_USAGE_NOTIFICATION"; 
 case IRP_MN_SURPRISE_REMOVAL: 
  return "IRP_MN_SURPRISE_REMOVAL";   
 default: 
  return "unknown_pnp_irp"; 
    } 
} 
#endif 
NTSTATUS 
DriverEntry( 
    IN PDRIVER_OBJECT  DriverObject, 
    IN PUNICODE_STRING RegistryPath 
    ) 
{ 
    NTSTATUS            status = STATUS_SUCCESS; 
    ULONG               ulIndex; 
    PDRIVER_DISPATCH  * dispatch; 
    UNREFERENCED_PARAMETER (RegistryPath); 
    KdBreakPoint(); 
 KdPrint (("观察:Entered the Driver Entry\n")); 
    // 
    // Create dispatch points 
    // 
    for (ulIndex = 0, dispatch = DriverObject->MajorFunction; 
         ulIndex <= IRP_MJ_MAXIMUM_FUNCTION; 
         ulIndex++, dispatch++) { 
        *dispatch = FilterPass; 
    } 
 DriverObject->MajorFunction[IRP_MJ_PNP]            = FilterDispatchPnp; 
    DriverObject->MajorFunction[IRP_MJ_POWER]          = FilterDispatchPower; 
    DriverObject->DriverExtension->AddDevice           = FilterAddDevice; 
 DriverObject->MajorFunction[IRP_MJ_SCSI]           = FilterDispatchScsi; 
    DriverObject->DriverUnload                         = FilterUnload; 
    // 
    // Set the following dispatch points as we will be doing 
    // something useful to these requests instead of just 
    // passing them down. 
    // 
    
    DriverObject->MajorFunction[IRP_MJ_CREATE]     = 
 DriverObject->MajorFunction[IRP_MJ_CLOSE]      = 
 DriverObject->MajorFunction[IRP_MJ_CLEANUP]    = 
 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = 
  FilterDispatchIo; 
    // 
    // Mutex is to synchronize multiple threads creating & deleting 
    // control deviceobjects. 
    // 
    ExInitializeFastMutex(&ControlMutex); 
    return status; 
} 
VOID 
FilterUnload( 
    IN PDRIVER_OBJECT DriverObject 
    ) 
{ 
    PAGED_CODE (); 
   
    ASSERT(DriverObject->DeviceObject == NULL); 
    
    KdPrint(("观察:Entry FilterUnload\n")); 
    return; 
} 
NTSTATUS 
FilterAddDeviceFun( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PDEVICE_OBJECT PhysicalDeviceObject, 
 IN USHORT bUSBSTORFILTERDEVICE, 
 IN OUT PDEVICE_OBJECT  *deviceObject 
    ) 
{ 
    NTSTATUS                status = STATUS_SUCCESS;     
    PDEVICE_EXTENSION       deviceExtension; 
    ULONG                   deviceType = FILE_DEVICE_DISK; 
    status = IoCreateDevice (DriverObject, 
                             sizeof (DEVICE_EXTENSION), 
                             NULL, 
                             deviceType, 
                             FILE_DEVICE_SECURE_OPEN, 
                             FALSE, 
                             deviceObject); 
    if (!NT_SUCCESS (status)) { 
        KdPrint (("IoCreateDevice Error:(0x%x)\n",status)); 
        return status; 
    } 
    KdPrint (("AddDevice PDO (0x%x) FDO (0x%x)\n", 
                    PhysicalDeviceObject, deviceObject)); 
    deviceExtension = (PDEVICE_EXTENSION)(*deviceObject)->DeviceExtension; 
  
    deviceExtension->NextLowerDriver = IoAttachDeviceToDeviceStack ( 
                                       *deviceObject, 
                                       PhysicalDeviceObject); 
 // 
    // Failure for attachment is an indication of a broken plug & play system. 
    // 
    if(NULL == deviceExtension->NextLowerDriver) 
 { 
  KdPrint (("注意了:FilterAddDevice:NULL==deviceExtension->NextLowerDriver\n")); 
        IoDeleteDevice(*deviceObject); 
        return STATUS_UNSUCCESSFUL; 
    } 
 (*deviceObject)->Flags |= deviceExtension->NextLowerDriver->Flags & 
                            (DO_BUFFERED_IO | DO_DIRECT_IO | 
                            DO_POWER_PAGABLE ); 

    (*deviceObject)->DeviceType=FILE_DEVICE_DISK; 
    (*deviceObject)->Characteristics = 
                          deviceExtension->NextLowerDriver->Characteristics; 
    deviceExtension->Self = (*deviceObject); 
    // 
    // Let us use remove lock to keep count of IRPs so that we don't 
    // deteach and delete our deviceobject until all pending I/Os in our 
    // devstack are completed. Remlock is required to protect us from 
    // various race conditions where our driver can get unloaded while we 
    // are still running dispatch or completion code. 
    // 
    
    IoInitializeRemoveLock (&deviceExtension->RemoveLock , 
                            POOL_TAG, 
                            1, // MaxLockedMinutes 
                            100); // HighWatermark, this parameter is 
                                // used only on checked build. Specifies 
                                // the maximum number of outstanding 
                                // acquisitions allowed on the lock 
                                
    // 
    // Set the initial state of the Filter DO 
    // 
    INITIALIZE_PNP_STATE(deviceExtension); 
 InitializeListHead(&deviceExtension->pFilterUsbStorListHead);  
 deviceExtension->bUSBSTORFILTERDEVICE=bUSBSTORFILTERDEVICE; 
    KdPrint(("AddDevice: %x to %x->%x \n", *deviceObject, 
                       deviceExtension->NextLowerDriver, 
                       PhysicalDeviceObject)); 
    (*deviceObject)->Flags &= ~DO_DEVICE_INITIALIZING; 
    return STATUS_SUCCESS; 
} 
NTSTATUS 
FilterAddDevice( 
    IN PDRIVER_OBJECT DriverObject, 
    IN PDEVICE_OBJECT PhysicalDeviceObject 
    ) 
{ 
    PDEVICE_OBJECT          deviceObject = NULL; 
    
    PAGED_CODE (); 
    return (FilterAddDeviceFun(DriverObject,PhysicalDeviceObject,0,&deviceObject)); 
} 

NTSTATUS 
FilterPass ( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
{ 
    PDEVICE_EXTENSION           deviceExtension; 
    NTSTATUS    status; 
     
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 
    status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp); 
    if (!NT_SUCCESS (status)) { 
        Irp->IoStatus.Status = status; 
        IoCompleteRequest (Irp, IO_NO_INCREMENT); 
        return status; 
    } 
   IoSkipCurrentIrpStackLocation (Irp); 
   status = IoCallDriver (deviceExtension->NextLowerDriver, Irp); 
   IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); 
   return status; 
} 
NTSTATUS 
FilterDispatchPower( 
     IN PDEVICE_OBJECT    DeviceObject, 
     IN PIRP              Irp 
     ) 
{ 
    PDEVICE_EXTENSION   deviceExtension; 
    NTSTATUS    status; 
    
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 
    status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp); 
    if (!NT_SUCCESS (status)) { // may be device is being removed. 
        Irp->IoStatus.Status = status; 
        PoStartNextPowerIrp(Irp); 
        IoCompleteRequest (Irp, IO_NO_INCREMENT); 
        return status; 
    } 
  
    PoStartNextPowerIrp(Irp); 
    IoSkipCurrentIrpStackLocation(Irp); 
    status = PoCallDriver(deviceExtension->NextLowerDriver, Irp); 
    IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); 
    return status; 
} 

NTSTATUS 
FilterDispatchPnp ( 
    IN PDEVICE_OBJECT DeviceObject, 
    IN PIRP Irp 
    ) 
{ 
    PDEVICE_EXTENSION           deviceExtension; 
    PIO_STACK_LOCATION         irpStack; 
    NTSTATUS                            status; 
    KEVENT                               event; 
 PHUA_ATTACHED_DEVICE pData=NULL; 
 PLIST_ENTRY pEntry=NULL; 
  
    PAGED_CODE(); 
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 
 if(deviceExtension->bUSBSTORFILTERDEVICE) 
 { 
  return FilterPass(DeviceObject,Irp); 
 } 
    irpStack = IoGetCurrentIrpStackLocation(Irp); 
    KdPrint(("FilterDO %s IRP:0x%x \n", 
                PnPMinorFunctionString(irpStack->MinorFunction), Irp)); 
   status = IoAcquireRemoveLock (&deviceExtension->RemoveLock, Irp); 
    if (!NT_SUCCESS (status)) { 
        Irp->IoStatus.Status = status; 
        IoCompleteRequest (Irp, IO_NO_INCREMENT); 
        return status; 
    } 
    switch (irpStack->MinorFunction) 
 { 
    case IRP_MN_START_DEVICE:   
        // 
        // The device is starting. 
        // We cannot touch the device (send it any non pnp irps) until a 
        // start device has been passed down to the lower drivers. 
        // 
  KeInitializeEvent(&event, NotificationEvent, FALSE); 
        IoCopyCurrentIrpStackLocationToNext(Irp); 
        IoSetCompletionRoutine(Irp, 
                               (PIO_COMPLETION_ROUTINE) FilterStartCompletionRoutine, 
                               &event, 
                               TRUE, 
                               TRUE, 
                               TRUE); 
        status = IoCallDriver(deviceExtension->NextLowerDriver, Irp);        
        // 
        // Wait for lower drivers to be done with the Irp. Important thing to 
        // note here is when you allocate memory for an event in the stack  
        // you must do a KernelMode wait instead of UserMode to prevent 
        // the stack from getting paged out. 
        // 
        if (status == STATUS_PENDING) { 
           KeWaitForSingleObject(&event, Executive, KernelMode, FALSE, NULL);          
           status = Irp->IoStatus.Status; 
        } 
        if (NT_SUCCESS (status)) { 
            // 
            // As we are successfully now back, we will 
            // first set our state to Started. 
            // 
            SET_NEW_PNP_STATE(deviceExtension, Started); 
            // 
            // On the way up inherit FILE_REMOVABLE_MEDIA during Start. 
            // This characteristic is available only after the driver stack is started!. 
            // 
            if (deviceExtension->NextLowerDriver->Characteristics & FILE_REMOVABLE_MEDIA) { 
                DeviceObject->Characteristics |= FILE_REMOVABLE_MEDIA; 
            }   
   // 
            // If the PreviousPnPState is stopped then we are being stopped temporarily 
            // and restarted for resource rebalance. 
            // 
            if(Stopped != deviceExtension->PreviousPnPState) { 
                // 
                // Device is started for the first time. 
                // 
                FilterCreateControlObject(DeviceObject); 
            } 
        } 
        
        Irp->IoStatus.Status = status; 
        IoCompleteRequest (Irp, IO_NO_INCREMENT); 
        IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); 
        return status; 
    case IRP_MN_REMOVE_DEVICE: 
        // 
        // Wait for all outstanding requests to complete 
        // 
        KdPrint(("Waiting for outstanding requests\n")); 
        IoReleaseRemoveLockAndWait(&deviceExtension->RemoveLock, Irp); 
        IoSkipCurrentIrpStackLocation(Irp); 
        status = IoCallDriver(deviceExtension->NextLowerDriver, Irp); 
        SET_NEW_PNP_STATE(deviceExtension, Deleted); 
        FilterDeleteControlObject(); 
        
  while(!IsListEmpty(&deviceExtension->pFilterUsbStorListHead)) 
  { 
   pEntry=RemoveTailList(&deviceExtension->pFilterUsbStorListHead); 
   pData=CONTAINING_RECORD(pEntry,HUA_ATTACHED_DEVICE,listEntry); 
   IoDetachDevice(pData->FilterUsbStorLowerDriver); 
   IoDeleteDevice(pData->FilterUsbStor); 
   ExFreePool(pData); 
  } 
  IoDetachDevice(deviceExtension->NextLowerDriver); 
  IoDeleteDevice(DeviceObject); 
        return status; 

    case IRP_MN_QUERY_STOP_DEVICE: 
        SET_NEW_PNP_STATE(deviceExtension, StopPending); 
        status = STATUS_SUCCESS; 
        break; 
    case IRP_MN_CANCEL_STOP_DEVICE: 
        // 
        // Check to see whether you have received cancel-stop 
        // without first receiving a query-stop. This could happen if someone 
        // above us fails a query-stop and passes down the subsequent 
        // cancel-stop. 
        // 
        if(StopPending == deviceExtension->DevicePnPState) 
        { 
            // 
            // We did receive a query-stop, so restore. 
            // 
            RESTORE_PREVIOUS_PNP_STATE(deviceExtension); 
        } 
        status = STATUS_SUCCESS; // We must not fail this IRP. 
        break; 
    case IRP_MN_STOP_DEVICE: 
        SET_NEW_PNP_STATE(deviceExtension, Stopped); 
        status = STATUS_SUCCESS; 
        break; 
    case IRP_MN_QUERY_REMOVE_DEVICE: 
        SET_NEW_PNP_STATE(deviceExtension, RemovePending); 
        status = STATUS_SUCCESS; 
        break; 
    case IRP_MN_SURPRISE_REMOVAL: 
        SET_NEW_PNP_STATE(deviceExtension, SurpriseRemovePending); 
        status = STATUS_SUCCESS; 
        break; 
    case IRP_MN_CANCEL_REMOVE_DEVICE: 
        // 
        // Check to see whether you have received cancel-remove 
        // without first receiving a query-remove. This could happen if 
        // someone above us fails a query-remove and passes down the 
        // subsequent cancel-remove. 
        // 
        if(RemovePending == deviceExtension->DevicePnPState) 
        { 
            // 
            // We did receive a query-remove, so restore. 
            // 
            RESTORE_PREVIOUS_PNP_STATE(deviceExtension); 
        } 
        status = STATUS_SUCCESS; // We must not fail this IRP. 
        break; 
    case IRP_MN_DEVICE_USAGE_NOTIFICATION: 
        // 
        // On the way down, pagable might become set. Mimic the driver 
        // above us. If no one is above us, just set pagable. 
        // 
        if ((DeviceObject->AttachedDevice == NULL) || 
            (DeviceObject->AttachedDevice->Flags & DO_POWER_PAGABLE)) { 
            DeviceObject->Flags |= DO_POWER_PAGABLE; 
        } 
        IoCopyCurrentIrpStackLocationToNext(Irp); 
        IoSetCompletionRoutine( 
            Irp, 
            FilterDeviceUsageNotificationCompletionRoutine, 
            NULL, 
            TRUE, 
            TRUE, 
            TRUE 
            ); 
        return IoCallDriver(deviceExtension->NextLowerDriver, Irp); 
 case IRP_MN_QUERY_DEVICE_RELATIONS: 
   status = Irp->IoStatus.Status; 
      break; 
    default: 
        // 
        // If you don't handle any IRP you must leave the 
        // status as is. 
        // 
        status = Irp->IoStatus.Status; 
        break; 
    } 
    // 
    // Pass the IRP down and forget it. 
    // 
    Irp->IoStatus.Status = status; 
    IoSkipCurrentIrpStackLocation (Irp); 
    status = IoCallDriver (deviceExtension->NextLowerDriver, Irp); 
    IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); 
    return status; 
} 
NTSTATUS 
FilterStartCompletionRoutine( 
    IN PDEVICE_OBJECT   DeviceObject, 
    IN PIRP             Irp, 
    IN PVOID            Context 
    ) 
{ 
    PKEVENT             event = (PKEVENT)Context; 
 // 
    UNREFERENCED_PARAMETER (DeviceObject); 
 // 
    // If the lower driver didn't return STATUS_PENDING, we don't need to 
    // set the event because we won't be waiting on it. 
    // This optimization avoids grabbing the dispatcher lock, and improves perf. 
    // 
    if (Irp->PendingReturned == TRUE) { 
        KeSetEvent (event, IO_NO_INCREMENT, FALSE); 
    } 
    // 
    // The dispatch routine will have to call IoCompleteRequest 
    // 
    return STATUS_MORE_PROCESSING_REQUIRED; 
} 
NTSTATUS 
FilterDeviceUsageNotificationCompletionRoutine( 
    IN PDEVICE_OBJECT   DeviceObject, 
    IN PIRP             Irp, 
    IN PVOID            Context 
    ) 
{ 
    PDEVICE_EXTENSION       deviceExtension; 
    UNREFERENCED_PARAMETER(Context); 
    deviceExtension = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 

    if (Irp->PendingReturned) { 
        IoMarkIrpPending(Irp); 
    } 
    // 
    // On the way up, pagable might become clear. Mimic the driver below us. 
    // 
    if (!(deviceExtension->NextLowerDriver->Flags & DO_POWER_PAGABLE)) { 
        DeviceObject->Flags &= ~DO_POWER_PAGABLE; 
    } 
    IoReleaseRemoveLock(&deviceExtension->RemoveLock, Irp); 
    return STATUS_CONTINUE_COMPLETION; 
} 
NTSTATUS 
FilterDispatchScsi(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp ) 
{ 
 PDEVICE_EXTENSION pdx; 
 PIO_STACK_LOCATION irpStack; 
 NTSTATUS status; 
 //KdPrint(("观察:进入FilterDispatchScsi\n")); 
 pdx = (PDEVICE_EXTENSION) DeviceObject->DeviceExtension; 
 if(pdx->bUSBSTORFILTERDEVICE) 
 { 
  status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);  
  if (!NT_SUCCESS (status)) 
  { 
   Irp->IoStatus.Status = status; 
   IoCompleteRequest (Irp, IO_NO_INCREMENT); 
   return status; 
  } 
  irpStack = IoGetCurrentIrpStackLocation(Irp); 
  if (flag==2) 
  { 
    IoCopyCurrentIrpStackLocationToNext(Irp);  
    IoSetCompletionRoutine(Irp,   
     USBSCSICompletion,  
     NULL,   
     TRUE,   
     TRUE,   
     TRUE );  
    status = IoCallDriver(pdx->NextLowerDriver, Irp);   
  } 
  else 
  { 
   IoSkipCurrentIrpStackLocation (Irp); 
   status = IoCallDriver (pdx->NextLowerDriver, Irp); 
  } 
  IoReleaseRemoveLock(&pdx->RemoveLock, Irp);  
 } 
 else if(DeviceObject->AttachedDevice!=NULL && 
  _wcsnicmp(DeviceObject->AttachedDevice->DriverObject->DriverName.Buffer,L"[url=file://\\Driver\\USBSTOR]\\Driver\\USBSTOR",15)==0[/url]) 
 { 
  status = IoAcquireRemoveLock(&pdx->RemoveLock, Irp);  
  if (!NT_SUCCESS (status)) 
  { 
   Irp->IoStatus.Status = status; 
   IoCompleteRequest (Irp, IO_NO_INCREMENT); 
   return status; 
  } 
  irpStack = IoGetCurrentIrpStackLocation(Irp); 
  // 
  if (flag==1) 
  {    
   Irp->IoStatus.Status = STATUS_ACCESS_DENIED; 
   Irp->IoStatus.Information = 0; 
   IoCompleteRequest( Irp, IO_NO_INCREMENT ); 
   return STATUS_ACCESS_DENIED;    
  } 
  else 
  {    
    IoCopyCurrentIrpStackLocationToNext(Irp); 
    IoSetCompletionRoutine(Irp,   
     USBSCSICompletion2,  
     DeviceObject->AttachedDevice,   
     TRUE,   
     TRUE,   
     TRUE );             
    status = IoCallDriver(pdx->NextLowerDriver, Irp);   
  }     
  IoReleaseRemoveLock(&pdx->RemoveLock, Irp);   
 }  
 else 
 { 
  return FilterPass(DeviceObject, Irp); 
 }  
 return status; 
} 

NTSTATUS 
USBSCSICompletion( IN PDEVICE_OBJECT DeviceObject,      
      IN PIRP Irp,      
      IN PVOID Context )      
{  
 PDEVICE_EXTENSION pdx; 
 PIO_STACK_LOCATION irpStack; 
 PSCSI_REQUEST_BLOCK CurSrb; 
 PCDB cdb; 
 UCHAR opCode; 
 PMODE_PARAMETER_HEADER modeData; 
    pdx = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension;  
  
 IoAcquireRemoveLock(&pdx->RemoveLock,Irp); 
  
 irpStack = IoGetCurrentIrpStackLocation( Irp ); 
 CurSrb=irpStack->Parameters.Scsi.Srb; 
 cdb = (PCDB)CurSrb->Cdb; 
 if(CurSrb && cdb) 
 {    
  opCode=cdb->CDB6GENERIC.OperationCode; 
  //if(opCode) 
  // DbgPrint("USBSCSICompletion: opCode=%d,CurSrb->DataBuffer=0x%x\n CurSrb->DataTransferLength=%d,%d\n", 
  // opCode,CurSrb->DataBuffer,CurSrb->DataTransferLength,sizeof(MODE_PARAMETER_HEADER)); 
  if(opCode==SCSIOP_MODE_SENSE  && CurSrb->DataBuffer 
   && CurSrb->DataTransferLength >= sizeof(MODE_PARAMETER_HEADER) 
   ) 
  { 
   KdPrint(("SCSIOP_MODE_SENSE comming:0x%x!\n",DeviceObject)); 
   modeData = (PMODE_PARAMETER_HEADER)CurSrb->DataBuffer; 
   modeData->DeviceSpecificParameter |= MODE_DSP_WRITE_PROTECT; 
  } 
  else if(opCode==SCSIOP_WRITE) 
  { 
   KdPrint(("SCSIOP_WRITE comming:0x%x!\n",DeviceObject)); 
   Irp->IoStatus.Status= STATUS_UNSUCCESSFUL;//难够拦截到,有出错提示,但是数据可以修改, 
  } 
 } 
      
 if ( Irp->PendingReturned )   
 {   
  IoMarkIrpPending( Irp );   
 }   
  
 IoReleaseRemoveLock(&pdx->RemoveLock,Irp);  
 return Irp->IoStatus.Status ;  
} 
NTSTATUS 
USBSCSICompletion2( IN PDEVICE_OBJECT DeviceObject,      
      IN PIRP Irp,      
      IN PVOID Context )      
{   
 NTSTATUS status; 
 PDEVICE_EXTENSION pdx; 
 pdx = ( PDEVICE_EXTENSION )DeviceObject->DeviceExtension; 
 IoAcquireRemoveLock(&pdx->RemoveLock,Irp);  
 // 
 status=CreateFilterUsbstoreObject(DeviceObject,(PDEVICE_OBJECT)Context); 
 //  
 if ( Irp->PendingReturned )   
 {   
  IoMarkIrpPending( Irp );   
 }   
 // 
 IoReleaseRemoveLock(&pdx->RemoveLock,Irp);  
 return status;  
}
hothua
驱动牛犊
驱动牛犊
  • 注册日期2006-06-20
  • 最后登录2009-11-17
  • 粉丝0
  • 关注0
  • 积分23分
  • 威望191点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分1分
6楼#
发布于:2009-10-05 09:33
NTSTATUS 
CreateFilterUsbstoreObject(IN PDEVICE_OBJECT    DeviceObject, 
         IN PDEVICE_OBJECT    UsbStorDeviceObject 
         ) 
{ 
 PDRIVER_OBJECT usbStor; 
 NTSTATUS status = STATUS_SUCCESS; 
 PDEVICE_OBJECT pFilterDeviceObject = NULL; 
    PDEVICE_OBJECT pTargetDeviceObject = NULL; 
 PDEVICE_OBJECT pTempDeviceObject = NULL;   
 PDEVICE_EXTENSION deviceExtension=NULL; 
 PDEVICE_EXTENSION deviceExtension1=NULL; 
 PHUA_ATTACHED_DEVICE pData=NULL;  
   
 usbStor=((PDEVICE_OBJECT)UsbStorDeviceObject)->DriverObject; 
 //这是设备链中的第一个设备  
 pTargetDeviceObject = usbStor->DeviceObject; 
 if(firstUsbStorDeviceObject==pTargetDeviceObject)//减少不必要的遍历设备链,前提是新加入的设备在头部加入 
 {   
  return( status ); 
 } 
 firstUsbStorDeviceObject=pTargetDeviceObject; 
 // 现在开始遍历这个设备链 
 while(pTargetDeviceObject) 
 { 
  pTempDeviceObject=pTargetDeviceObject; 
  while((pTempDeviceObject=pTempDeviceObject->AttachedDevice)!=NULL) 
  {   
   if(pTempDeviceObject->DriverObject==DeviceObject->DriverObject) 
    break; 
  } 
  if(NULL==pTempDeviceObject) 
  { 
   status=FilterAddDeviceFun(DeviceObject->DriverObject,pTargetDeviceObject,1,&pFilterDeviceObject); 
   if (NT_SUCCESS( status )) { 
    deviceExtension=(PDEVICE_EXTENSION)DeviceObject->DeviceExtension; 
    deviceExtension1=(PDEVICE_EXTENSION)pFilterDeviceObject->DeviceExtension; 
    pData=(PHUA_ATTACHED_DEVICE)ExAllocatePool(PagedPool,sizeof(HUA_ATTACHED_DEVICE)); 
    pData->FilterUsbStor=deviceExtension1->Self; 
    pData->FilterUsbStorLowerDriver=deviceExtension1->NextLowerDriver; 
    InsertTailList(&deviceExtension->pFilterUsbStorListHead,&pData->listEntry); 
   } 
  }   
  pTargetDeviceObject=pTargetDeviceObject->NextDevice; 
 }  
 return( status ); 
} 
// 
NTSTATUS 
FilterCreateControlObject( 
    IN PDEVICE_OBJECT    DeviceObject 
) 
{ 
    UNICODE_STRING      ntDeviceName; 
    UNICODE_STRING      symbolicLinkName; 
    PCONTROL_DEVICE_EXTENSION   deviceExtension; 
    NTSTATUS status = STATUS_UNSUCCESSFUL; 
    UNICODE_STRING  sddlString;    
    PAGED_CODE();    
    // 
    // Using unsafe function so that the IRQL remains at PASSIVE_LEVEL. 
    // IoCreateDeviceSecure & IoCreateSymbolicLink must be called at 
    // PASSIVE_LEVEL. 
    // 
    ExAcquireFastMutexUnsafe(&ControlMutex); 
    // 
    // If this is a first instance of the device, then create a controlobject 
    // and register dispatch points to handle ioctls. 
    // 
    if(1 == ++InstanceCount) 
    { 
        // 
        // Initialize the unicode strings 
        // 
        RtlInitUnicodeString(&ntDeviceName, NTDEVICE_NAME_STRING); 
        RtlInitUnicodeString(&symbolicLinkName, SYMBOLIC_NAME_STRING); 
        // 
        // Initialize a security descriptor string. Refer to SDDL docs in the SDK 
        // for more info. 
        // 
        RtlInitUnicodeString( &sddlString, L"D:P(A;;GA;;;SY)(A;;GA;;;BA)"); 
        // 
        // Create a named deviceobject so that applications or drivers 
        // can directly talk to us without going throuhg the entire stack. 
        // This call could fail if there are not enough resources or 
        // another deviceobject of same name exists (name collision). 
        // Let us use the new IoCreateDeviceSecure and specify a security 
        // descriptor (SD) that allows only System and Admin groups to access the 
        // control device. Let us also specify a unique guid to allow administrators 
        // to change the SD if he desires to do so without changing the driver. 
        // The SD will be stored in 
        // HKLM\SYSTEM\CCSet\Control\Class\<GUID>\Properties\Security. 
        // An admin can override the SD specified in the below call by modifying 
        // the registry. 
        // 
        
        status = IoCreateDeviceSecure(DeviceObject->DriverObject, 
                                sizeof(CONTROL_DEVICE_EXTENSION), 
                                &ntDeviceName, 
                                FILE_DEVICE_UNKNOWN, 
                                FILE_DEVICE_SECURE_OPEN, 
                                FALSE, 
                                &sddlString, 
                                (LPCGUID)&GUID_SD_FILTER_CONTROL_OBJECT, 
                                &ControlDeviceObject); 
        if (NT_SUCCESS( status )) { 
            ControlDeviceObject->Flags |= DO_BUFFERED_IO; 
            status = IoCreateSymbolicLink( &symbolicLinkName, &ntDeviceName ); 
            if ( !NT_SUCCESS( status )) { 
                IoDeleteDevice(ControlDeviceObject); 
                KdPrint(("IoCreateSymbolicLink failed %x\n", status)); 
                goto End; 
            } 
            deviceExtension = ControlDeviceObject->DeviceExtension; 
            deviceExtension->ControlData = NULL; 
            deviceExtension->Deleted = FALSE; 
            
            ControlDeviceObject->Flags &= ~DO_DEVICE_INITIALIZING; 
            
        }else { 
            KdPrint(("IoCreateDevice failed %x\n", status)); 
        } 
    } 
End: 
    
    ExReleaseFastMutexUnsafe(&ControlMutex); 
    return status; 
    
} 
VOID 
FilterDeleteControlObject( 
) 
{ 
    UNICODE_STRING      symbolicLinkName; 
    PCONTROL_DEVICE_EXTENSION   deviceExtension; 
    PAGED_CODE();    
    ExAcquireFastMutexUnsafe (&ControlMutex); 
    // 
    // If this is the last instance of the device then delete the controlobject 
    // and symbolic link to enable the pnp manager to unload the driver. 
    // 
    
    if(!(--InstanceCount) && ControlDeviceObject) 
    { 
        RtlInitUnicodeString(&symbolicLinkName, SYMBOLIC_NAME_STRING); 
        deviceExtension = ControlDeviceObject->DeviceExtension; 
        deviceExtension->Deleted = TRUE; 
        IoDeleteSymbolicLink(&symbolicLinkName); 
        IoDeleteDevice(ControlDeviceObject); 
        ControlDeviceObject = NULL; 
    } 
    ExReleaseFastMutexUnsafe (&ControlMutex); 
} 
// 
NTSTATUS 
ProcessControl(IN PIRP              Irp , 
      IN PIO_STACK_LOCATION    irpStack) 
{ 
 PVOID                   inputBuffer; 
 CHAR     n; 
 NTSTATUS               status=STATUS_SUCCESS; 
  
 KdPrint(("观察:Entry ProcessControl!\n"));  
  
 if (irpStack->Parameters.DeviceIoControl.IoControlCode==IOCTL_820) 
 { 
  inputBuffer = Irp->AssociatedIrp.SystemBuffer; 
  DbgPrint("我得到了IOCTL_800并且inputBuffer=%s\n",inputBuffer); 
  n=*(CHAR*)inputBuffer; 
  KdPrint(("n=%d;flag=%d\n",n,flag)); 
  if(n>=0 && n<=2) 
   flag=n;  
  else 
   status = STATUS_INVALID_PARAMETER;   
 } 
 else 
 { 
  status = STATUS_INVALID_PARAMETER; 
 } 
 return status; 
} 
// 
NTSTATUS 
FilterDispatchIo( 
    IN PDEVICE_OBJECT    DeviceObject, 
    IN PIRP              Irp  
    ) 
{ 
    PIO_STACK_LOCATION  irpStack; 
    NTSTATUS            status; 
    PCONTROL_DEVICE_EXTENSION   deviceExtension; 
    PAGED_CODE(); 
    // 
    // Please note that this is a common dispatch point for controlobject and 
    // filter deviceobject attached to the pnp stack. 
    // 
    if(DeviceObject != ControlDeviceObject) { 
        // 
        // We will just  the request down as we are not interested in handling 
        // requests that come on the PnP stack. 
        // 
        return FilterPass(DeviceObject, Irp);    
    } 
   deviceExtension = ControlDeviceObject->DeviceExtension; 
    
    // 
    // Else this is targeted at our control deviceobject so let's handle it. 
    // Here we will handle the IOCTl requests that come from the app. 
    // We don't have to worry about acquiring remlocks for I/Os that come 
    // on our control object because the I/O manager takes reference on our 
    // deviceobject when it initiates a request to our device and that keeps 
    // our driver from unloading when we have pending I/Os. But we still 
    // have to watch out for a scenario where another driver can send 
    // requests to our deviceobject directly without opening an handle. 
    // 
    if(!deviceExtension->Deleted) { //if not deleted 
        status = STATUS_SUCCESS; 
        Irp->IoStatus.Information = 0; 
        irpStack = IoGetCurrentIrpStackLocation (Irp); 
        switch (irpStack->MajorFunction) { 
            case IRP_MJ_CREATE: 
                KdPrint(("Create \n")); 
                break; 
                
            case IRP_MJ_CLOSE: 
                KdPrint(("Close \n")); 
                break; 
                
            case IRP_MJ_CLEANUP: 
                KdPrint(("Cleanup \n")); 
                break; 
                
             case  IRP_MJ_DEVICE_CONTROL: 
                KdPrint(("DeviceIoControl\n")); 
    status =ProcessControl(Irp,irpStack); 
                break; 
            default: 
                break; 
        } 
    } 
 else { 
        ASSERTMSG(FALSE, "Requests being sent to a dead device\n"); 
        status = STATUS_DEVICE_REMOVED; 
    } 
    Irp->IoStatus.Status = status; 
    IoCompleteRequest (Irp, IO_NO_INCREMENT); 
    return status; 
}
qhadronj
驱动牛犊
驱动牛犊
  • 注册日期2008-12-23
  • 最后登录2010-09-12
  • 粉丝0
  • 关注0
  • 积分13分
  • 威望121点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
7楼#
发布于:2009-10-08 22:43
我现在也在搞这个驱动,对单个U盘的控制怎么实现呀,比如插入两个U盘,一个为可控,一个为不可控,有兴趣的话我们共同讨论,QQ:329673470
xujd0451
驱动牛犊
驱动牛犊
  • 注册日期2009-07-27
  • 最后登录2010-07-07
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
8楼#
发布于:2009-10-10 10:14
look looka
xujd0451
驱动牛犊
驱动牛犊
  • 注册日期2009-07-27
  • 最后登录2010-07-07
  • 粉丝0
  • 关注0
  • 积分20分
  • 威望251点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
9楼#
发布于:2009-10-10 10:14
woyaokanbkna
happylife365
驱动牛犊
驱动牛犊
  • 注册日期2002-10-01
  • 最后登录2013-08-17
  • 粉丝1
  • 关注0
  • 积分80分
  • 威望394点
  • 贡献值1点
  • 好评度1点
  • 原创分0分
  • 专家分0分
10楼#
发布于:2009-10-13 23:11
支持一下楼主辛苦工作
快快乐乐过日子,潇潇洒洒闯人生。
wkingg
驱动牛犊
驱动牛犊
  • 注册日期2009-10-13
  • 最后登录2009-10-28
  • 粉丝0
  • 关注0
  • 积分3分
  • 威望31点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
11楼#
发布于:2009-10-14 09:37
谢了.下回来看看
yincheng01
驱动牛犊
驱动牛犊
  • 注册日期2009-10-15
  • 最后登录2010-11-03
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望51点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
12楼#
发布于:2009-10-16 09:19
ding
yincheng01
驱动牛犊
驱动牛犊
  • 注册日期2009-10-15
  • 最后登录2010-11-03
  • 粉丝0
  • 关注0
  • 积分5分
  • 威望51点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
13楼#
发布于:2009-10-16 09:20
dingdie
Zhang3612
驱动牛犊
驱动牛犊
  • 注册日期2008-07-19
  • 最后登录2011-02-28
  • 粉丝0
  • 关注0
  • 积分18分
  • 威望145点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
14楼#
发布于:2009-10-27 22:40
ok ok
驱网无线,快乐无限
xum2008
驱动牛犊
驱动牛犊
  • 注册日期2009-05-08
  • 最后登录2014-08-10
  • 粉丝0
  • 关注0
  • 积分75分
  • 威望741点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
15楼#
发布于:2009-10-28 17:28
还在学习中。。。
caterpillar1234
驱动牛犊
驱动牛犊
  • 注册日期2009-07-18
  • 最后登录2012-02-29
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望81点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
16楼#
发布于:2009-10-29 08:27
good
caterpillar1234
驱动牛犊
驱动牛犊
  • 注册日期2009-07-18
  • 最后登录2012-02-29
  • 粉丝0
  • 关注0
  • 积分9分
  • 威望81点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
17楼#
发布于:2009-10-29 08:28
goood gooodd
killoneself
驱动牛犊
驱动牛犊
  • 注册日期2009-07-06
  • 最后登录2009-12-14
  • 粉丝0
  • 关注0
  • 积分11分
  • 威望101点
  • 贡献值0点
  • 好评度0点
  • 原创分0分
  • 专家分0分
18楼#
发布于:2009-10-31 11:04
goood gooodd
luckyxjb2010
驱动牛犊
驱动牛犊
  • 注册日期2009-10-18
  • 最后登录2009-12-09
  • 粉丝0
  • 关注0
  • 积分10分
  • 威望91点
  • 贡献值1点
  • 好评度0点
  • 原创分0分
  • 专家分0分
19楼#
发布于:2009-11-02 13:54
看看
上一页
游客

返回顶部