用户模式下用setupapi 与hid设备通讯正常 驱动中使用 IoGetDeviceInterfaces 能看到目标驱动IoGetDeviceObjectPointer 打开设备也成功了用IOCTL_HID_GET_COLLECTION_INFORMATION 跟目标hid设备通讯 IoCallDriver 返回Status 为success 但是返回的缓冲区是空的不知道如何纠错 求助
解决方案 »
- 既然cmd不支持Unicode,那么WriteConsoleW函数岂不是没有必要存在了?
- 股票软件界面结构-解决问题可以付现金。
- VS2005 专业版和企业版有哪些区别?
- WIN2000高手请进,谢谢非常!!
- waveOut* 及IID_IAudioData
- 请问怎样快速判断一个点在一个区域(region)内?(注意是快速,PtInRegion的不要)
- 菜鸟问题:WIN2K下实现套接字的偷窥
- 菜鸟求助!获解立刻揭贴!
- 学习vc++2010的书?
- 我发现很多朋友问vc开发数据库的问题,现在用vc搞数据库开发很多吗。
- 【求助】SDK创建的状态栏怎么不显示???
- 在多个控制件中,如何获取当前所点击控件的ID?
#pragma code_seg()
bool LinkToGamePad(PDRIVER_OBJECT DriverObject)
{
PMY_DEVICE_EXTENSION pDevExt=(PMY_DEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension;
KdPrint(("==============================================\n"));
#if DBG
{
KIRQL uIrql = KeGetCurrentIrql();
KdPrint(("%s is run on level: %x\n", __FUNCTION__, uIrql));
}
#endif
KdPrint(("KbFilter: enter LinkToGamePad\n"));
NTSTATUS Status;
PWSTR pDeviceList;
PWSTR pTemp;
UNICODE_STRING TempDeviceName;
PDEVICE_OBJECT TempDeviceObject;
PMY_PDRIVER_EXTENSION pMyDriverExt=(PMY_PDRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject,(PVOID)TAG_MY_DRIVER_EXTENSION); Status = IoGetDeviceInterfaces((LPGUID)&GUID_DEVINTERFACE_HID,NULL,DEVICE_INTERFACE_INCLUDE_NONACTIVE,&pDeviceList);
if (!NT_SUCCESS(Status))
{
KdPrint(( "KbFilter: IoGetDeviceInterfaces() failed with error %d\n",Status));
KdPrint(("KbFilter: leave LinkToGamePad\n"));
KdPrint(("KbFilter: ==============================================\n\n"));
return FALSE;
}
KdPrint(("IoGetDeviceInterfaces success \n")); if(pDeviceList==NULL)
{
KdPrint(("pDeviceList = NULL ")); } pTemp=pDeviceList;
Status=NULL;
while (*pTemp != UNICODE_NULL)
{
RtlInitUnicodeString( &TempDeviceName, pTemp );
KdPrint(("TempDeviceName = %ws",TempDeviceName.Buffer));
///--- //OBJECT_ATTRIBUTES object_attributes;
//IO_STATUS_BLOCK status_block; //InitializeObjectAttributes(&object_attributes,&TempDeviceName,OBJ_CASE_INSENSITIVE,NULL,NULL);
//Status=ZwCreateFile(&hDevice,FILE_WRITE_ATTRIBUTES|SYNCHRONIZE,&object_attributes,&status_block,NULL,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_WRITE|FILE_SHARE_READ,FILE_OPEN_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0); PFILE_OBJECT FileObject;
Status=IoGetDeviceObjectPointer ( &TempDeviceName, FILE_ALL_ACCESS,(PFILE_OBJECT*)&FileObject,&TempDeviceObject );
if (!NT_SUCCESS(Status))
{
DbgPrint( "KbFilter: IoGetDeviceObjectPointer() failed %x\n", Status);
//ExFreePool(pDeviceList);
//return FALSE;
}
else
{
KdPrint(("KbFilter: IoGetDeviceObjectPointer success\n")); pMyDriverExt->FileObject=FileObject;
if (CheckIfOurDevice(DriverObject,TempDeviceObject))
{
pDevExt->GamePadDeviceObject=TempDeviceObject;
KdPrint(("kbFilter : found my device! \n"));
if(pDeviceList)
{
ExFreePool(pDeviceList);
}
return TRUE;
}
else
{
ObDereferenceObject( FileObject );
}
}
pTemp+= (TempDeviceName.Length + sizeof( UNICODE_NULL ))/sizeof(WCHAR);
}
if(pDeviceList)
{
ExFreePool(pDeviceList);
}
KdPrint(("KbFilter: open and check all hid device ,but not find our device\n"));
KdPrint(("==============================================\n\n"));
return FALSE;
}#pragma code_seg("PAGE")
void ReleaseResource(PDRIVER_OBJECT DriverObject)
{
PMY_DEVICE_EXTENSION pDevExt=(PMY_DEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension;
KdPrint(("==============================================\n"));
PMY_PDRIVER_EXTENSION pMyDriverExt=(PMY_PDRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject,(PVOID)TAG_MY_DRIVER_EXTENSION);
ObDereferenceObject(pMyDriverExt->FileObject);
#if DBG
{
KIRQL uIrql = KeGetCurrentIrql();
KdPrint(("%s is run on level: %x\n", __FUNCTION__, uIrql));
}
#endif
KdPrint(("==============================================\n\n"));
}#pragma code_seg("PAGE")
bool CheckIfOurDevice(PDRIVER_OBJECT DriverObject,PDEVICE_OBJECT DeviceObject)
{
KdPrint(("==============================================\n"));
KdPrint(("KbFilter: enter CheckIfOurDevice\n"));
#if DBG
{
KIRQL uIrql = KeGetCurrentIrql(); KdPrint(("%s is run on level: %x\n", __FUNCTION__, uIrql));
}
#endif
PHIDP_PREPARSED_DATA PreparsedData=NULL; // The opaque parser info describing this device
HIDP_CAPS Caps; // The Capabilities of this hid device.
//USAGE MyUsagePage = 0xff00;
//USAGE MyUsage = 0x0001;
USAGE MyUsagePage = 0x01; //desktop
USAGE MyUsage = 0x05; //GamePad
LONG i=0;
NTSTATUS Status; //---------------------- ioctl部分
HID_COLLECTION_INFORMATION hci;
RtlZeroMemory(&hci,sizeof(HID_COLLECTION_INFORMATION));
Status=KernelDeviceIoControlsySynchronize(IOCTL_HID_GET_COLLECTION_INFORMATION,DriverObject,DeviceObject,NULL,0,(PVOID)&hci,sizeof(HID_COLLECTION_INFORMATION));
if(!NT_SUCCESS(Status))
{
KdPrint(("KbFilter: KernelDeviceIoControlsySynchronize failed\n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
return FALSE;
}
KdPrint(("KbFilter: KernelDeviceIoControlsySynchronize success\n"));
KdPrint(("hci.DescriptorSize =%x \n",hci.DescriptorSize));
KdPrint(("hci.ProductID %x \n",hci.ProductID));
KdPrint(("hci.VendorID %x \n",hci.VendorID)); for(;i<10 && PreparsedData==NULL;i++)
{
PreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePoolWithTag(NonPagedPool,hci.DescriptorSize,TAG_PreparsedData);
if(PreparsedData==NULL)
{
KdPrint(("KbFilter: allocate memory for preparsedData failed no enough memory\n"));
KdPrint(("KbFilter: now allocate once again %x\n",i));
}
}
if(!PreparsedData)
{
KdPrint(("KbFilter: allocate memory for preparsedData failed no enough memory\n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
return FALSE;
}
KdPrint(("KbFilter: allocate memory for preparsedData success \n "));
//Status=DeviceIoControl(file,IOCTL_HID_GET_COLLECTION_DESCRIPTOR,controlInfo,bufferSize,controlInfo,bufferSize,&BytesRet,0);
Status=KernelDeviceIoControlsySynchronize(IOCTL_HID_GET_COLLECTION_DESCRIPTOR,DriverObject,DeviceObject,NULL,0,(PVOID)PreparsedData,hci.DescriptorSize);
//此函数只能运行于passive级别
if (!HidP_GetCaps (PreparsedData, &Caps))
{
KdPrint(("KbFilter: Error: HidP_GetCaps failed \n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
if(PreparsedData)
{
ExFreePoolWithTag(PreparsedData,TAG_PreparsedData);
}
return FALSE;
}
if ((Caps.UsagePage == MyUsagePage) && (Caps.Usage == MyUsage))
{
KdPrint(("KbFilter: Success: Found my device.. \n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
if(PreparsedData)
{
ExFreePoolWithTag(PreparsedData,TAG_PreparsedData);
}
return TRUE;
}
KdPrint(("KbFilter: can not found my device \n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
if(PreparsedData)
{
ExFreePoolWithTag(PreparsedData,TAG_PreparsedData);
}
return FALSE;
}#pragma code_seg()
bool SendHidRequests(PDRIVER_OBJECT DriverObject,PDEVICE_OBJECT DeviceObject,UCHAR ReportID,UCHAR CtlCode)
{
PHIDMINI_CONTROL_INFO controlInfo = NULL;
NTSTATUS Status;
ULONG bufferSize;
KdPrint(("==============================================\n"));
KdPrint(("KbFilter: enter SendHidRequests\n"));
#if DBG
{
KIRQL uIrql = KeGetCurrentIrql(); KdPrint(("%s is run on level: %x\n", __FUNCTION__, uIrql));
}
#endif
bufferSize = sizeof (HIDMINI_CONTROL_INFO)
+ sizeof (HID_DEVICE_ATTRIBUTES); controlInfo = (PHIDMINI_CONTROL_INFO)ExAllocatePoolWithTag(PagedPool,bufferSize,TAG_HIDMINI_CONTROL_INFO); if (!controlInfo )
{
KdPrint(("ExAllocatePoolWithTag for PHIDMINI_CONTROL_INFO failed\n")); return false ;
}
controlInfo->ReportId = ReportID;
controlInfo->ControlCode=CtlCode;
// Status=DeviceIoControl(file, IOCTL_HID_GET_FEATURE,NULL,0,controlInfo,bufferSize,&BytesRet,NULL);
//-----------------------------ioctl部分
Status= KernelDeviceIoControlsySynchronize(IOCTL_HID_GET_FEATURE,DriverObject,DeviceObject,NULL,0,(PVOID)controlInfo,bufferSize);
if(!NT_SUCCESS(Status))
{
KdPrint(("KbFilter: failed IOCTL_HID_GET_FEATURE\n"));
if(controlInfo!=NULL)
{
ExFreePoolWithTag(controlInfo,TAG_HIDMINI_CONTROL_INFO);
}
return false;
}else
{
KdPrint(("KbFilter: success IOCTL_HID_GET_FEATURE\n"));
} //---------------------------------- KdPrint(("KbFilter: leave SendHidRequests\n"));
KdPrint(("==============================================\n\n"));
if(controlInfo!=NULL)
{
ExFreePoolWithTag(controlInfo,TAG_HIDMINI_CONTROL_INFO);
}
return true;
}code]
#pragma code_seg()
NTSTATUS KernelDeviceIoControlsySynchronize(ULONG IOCTL_CODE,PDRIVER_OBJECT DriverObject,PDEVICE_OBJECT TargetDeviceObject,PVOID inputbuffer,ULONG inputsize,PVOID outputbuffer,ULONG outputsize)
{
KdPrint(("==============================================\n"));
KdPrint(("KbFilter: enter KernelDeviceIoControlsySynchronize\n"));
#if DBG
{
KIRQL uIrql = KeGetCurrentIrql();
KdPrint(("%s is run on level: %x\n", __FUNCTION__, uIrql));
}
#endif
//---------------------- ioctl部分
NTSTATUS Status;
// ULONG BytesRet;
KEVENT GFEvent;
KeInitializeEvent(&GFEvent,SynchronizationEvent,FALSE);
PIO_STATUS_BLOCK io_status_block=NULL;
PIO_STACK_LOCATION IrpStack;
PMY_PDRIVER_EXTENSION pMyDriverExt;
//while(TargetDeviceObject->AttachedDevice!=NULL)
//{
// TargetDeviceObject=TargetDeviceObject->AttachedDevice;
//}
pMyDriverExt=(PMY_PDRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject,(PVOID)TAG_MY_DRIVER_EXTENSION); PIRP pIrp=NULL;
pIrp=IoBuildDeviceIoControlRequest(IOCTL_CODE,TargetDeviceObject,inputbuffer,inputsize,outputbuffer,outputsize,TRUE,&GFEvent,io_status_block);
if(NULL==pIrp)
{
KdPrint(("KbFilter: IoBuildDeviceIoControlRequest create Irp failed\n"));
return STATUS_UNSUCCESSFUL;
}
else
{
KdPrint(("KbFilter: IoBuildDeviceIoControlRequest Create Irp success\n"));
}
IrpStack = IoGetNextIrpStackLocation(pIrp);
IrpStack->FileObject =pMyDriverExt->FileObject;
Status=IoCallDriver(TargetDeviceObject,pIrp); if (Status==STATUS_PENDING)
{ KdPrint(("Io Call Driver pending\n"));
Status=KeWaitForSingleObject(&GFEvent,Executive,KernelMode,FALSE,NULL);
if(NT_SUCCESS(Status))
{
KdPrint(("Io Call Driver Success\n"));
Status=io_status_block->Status;
goto ___next;
}
else
{
KdPrint(("Io Call Driver failed\n"));
Status=io_status_block->Status;
return Status;
KdPrint(("KbFilter: leave KernelDeviceIoControlsySynchronize\n"));
KdPrint(("==============================================\n\n")); }
} if(!NT_SUCCESS(Status))
{
KdPrint(("KbFilter:IoCallDriver Failed %x\n",IOCTL_CODE));
return STATUS_UNSUCCESSFUL;
}
else
{
KdPrint(("KbFilter:IoCallDriver success %x\n",IOCTL_CODE)); }
___next:
KdPrint(("KbFilter: leave KernelDeviceIoControlsySynchronize\n"));
KdPrint(("==============================================\n\n"));
return Status;
}
用户模式调用DeviceIoControl可以?
#pragma code_seg()
bool LinkToGamePad(PDRIVER_OBJECT DriverObject)
{
PMY_DEVICE_EXTENSION pDevExt=(PMY_DEVICE_EXTENSION)DriverObject->DeviceObject->DeviceExtension;
KdPrint(("==============================================\n"));
#if DBG
{
KIRQL uIrql = KeGetCurrentIrql();
KdPrint(("%s is run on level: %x\n", __FUNCTION__, uIrql));
}
#endif
KdPrint(("KbFilter: enter LinkToGamePad\n"));
NTSTATUS Status;
PWSTR pDeviceList;
PWSTR pTemp;
UNICODE_STRING TempDeviceName;
PDEVICE_OBJECT TempDeviceObject;
PMY_PDRIVER_EXTENSION pMyDriverExt=(PMY_PDRIVER_EXTENSION)IoGetDriverObjectExtension(DriverObject,(PVOID)TAG_MY_DRIVER_EXTENSION);
Status = IoGetDeviceInterfaces((LPGUID)&GUID_DEVINTERFACE_HID,NULL,DEVICE_INTERFACE_INCLUDE_NONACTIVE,&pDeviceList);
if (!NT_SUCCESS(Status))
{
KdPrint(( "KbFilter: IoGetDeviceInterfaces() failed with error %d\n",Status));
KdPrint(("KbFilter: leave LinkToGamePad\n"));
KdPrint(("KbFilter: ==============================================\n\n"));
return FALSE; }
KdPrint(("IoGetDeviceInterfaces success \n"));
if(pDeviceList==NULL)
{
KdPrint(("pDeviceList = NULL ")); }
pTemp=pDeviceList;
Status=NULL;
while (*pTemp != UNICODE_NULL)
{
RtlInitUnicodeString( &TempDeviceName, pTemp );
KdPrint(("TempDeviceName = %ws",TempDeviceName.Buffer));
PFILE_OBJECT FileObject;
Status=IoGetDeviceObjectPointer ( &TempDeviceName, FILE_ALL_ACCESS,(PFILE_OBJECT*)&FileObject,&TempDeviceObject );
if (!NT_SUCCESS(Status))
{
DbgPrint( "KbFilter: IoGetDeviceObjectPointer() failed %x\n", Status);
}
else
{
KdPrint(("KbFilter: IoGetDeviceObjectPointer success\n")); pMyDriverExt->FileObject=FileObject;
if (CheckIfOurDevice(DriverObject,TempDeviceObject))
{
pDevExt->GamePadDeviceObject=TempDeviceObject;
KdPrint(("kbFilter : found my device! \n"));
if(pDeviceList)
{
ExFreePool(pDeviceList);
}
return TRUE;
}
else
{
ObDereferenceObject( FileObject );
}
}
pTemp+= (TempDeviceName.Length + sizeof( UNICODE_NULL ))/sizeof(WCHAR);
}
if(pDeviceList)
{
ExFreePool(pDeviceList);
}
KdPrint(("KbFilter: open and check all hid device ,but not find our device\n"));
KdPrint(("==============================================\n\n"));
return FALSE;}#pragma code_seg("PAGE")
bool CheckIfOurDevice(PDRIVER_OBJECT DriverObject,PDEVICE_OBJECT DeviceObject)
{
KdPrint(("==============================================\n"));
KdPrint(("KbFilter: enter CheckIfOurDevice\n"));
#if DBG
{
KIRQL uIrql = KeGetCurrentIrql();
KdPrint(("%s is run on level: %x\n", __FUNCTION__, uIrql));
}
#endif
PHIDP_PREPARSED_DATA PreparsedData=NULL; // The opaque parser info describing this device
HIDP_CAPS Caps; // The Capabilities of this hid device.
USAGE MyUsagePage = 0x01; //desktop
USAGE MyUsage = 0x05; //GamePad
LONG i=0;
NTSTATUS Status;
HID_COLLECTION_INFORMATION hci;
RtlZeroMemory(&hci,sizeof(HID_COLLECTION_INFORMATION));
Status=KernelDeviceIoControlsySynchronize(IOCTL_HID_GET_COLLECTION_INFORMATION,DriverObject,DeviceObject,NULL,0,(PVOID)&hci,sizeof(HID_COLLECTION_INFORMATION));
if(!NT_SUCCESS(Status))
{
KdPrint(("KbFilter: KernelDeviceIoControlsySynchronize failed\n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
return FALSE;
}
KdPrint(("KbFilter: KernelDeviceIoControlsySynchronize success\n"));
KdPrint(("hci.DescriptorSize =%x \n",hci.DescriptorSize));
KdPrint(("hci.ProductID %x \n",hci.ProductID));
KdPrint(("hci.VendorID %x \n",hci.VendorID));
for(;i<10 && PreparsedData==NULL;i++)
{
PreparsedData = (PHIDP_PREPARSED_DATA)ExAllocatePoolWithTag(NonPagedPool,hci.DescriptorSize,TAG_PreparsedData);
if(PreparsedData==NULL)
{
KdPrint(("KbFilter: allocate memory for preparsedData failed no enough memory\n"));
KdPrint(("KbFilter: now allocate once again %x\n",i));
}
}
if(!PreparsedData)
{
KdPrint(("KbFilter: allocate memory for preparsedData failed no enough memory\n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
return FALSE;
}
KdPrint(("KbFilter: allocate memory for preparsedData success \n "));
Status=KernelDeviceIoControlsySynchronize(IOCTL_HID_GET_COLLECTION_DESCRIPTOR,DriverObject,DeviceObject,NULL,0,(PVOID)PreparsedData,hci.DescriptorSize);
//此函数只能运行于passive级别
if (!HidP_GetCaps (PreparsedData, &Caps))
{
KdPrint(("KbFilter: Error: HidP_GetCaps failed \n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
if(PreparsedData)
{
ExFreePoolWithTag(PreparsedData,TAG_PreparsedData);
}
return FALSE;
}
if ((Caps.UsagePage == MyUsagePage) && (Caps.Usage == MyUsage))
{
KdPrint(("KbFilter: Success: Found my device.. \n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
if(PreparsedData)
{
ExFreePoolWithTag(PreparsedData,TAG_PreparsedData);
}
return TRUE;
}
KdPrint(("KbFilter: can not found my device \n"));
KdPrint(("KbFilter: leave CheckIfOurDevice\n"));
KdPrint(("==============================================\n\n"));
if(PreparsedData)
{
ExFreePoolWithTag(PreparsedData,TAG_PreparsedData);
}
return FALSE;
}
#pragma code_seg()
bool SendHidRequests(PDRIVER_OBJECT DriverObject,PDEVICE_OBJECT DeviceObject,UCHAR ReportID,UCHAR CtlCode)
{
PHIDMINI_CONTROL_INFO controlInfo = NULL;
NTSTATUS Status;
ULONG bufferSize;
KdPrint(("==============================================\n"));
KdPrint(("KbFilter: enter SendHidRequests\n"));
#if DBG
{
KIRQL uIrql = KeGetCurrentIrql();
KdPrint(("%s is run on level: %x\n", __FUNCTION__, uIrql));
}
#endif
bufferSize = sizeof (HIDMINI_CONTROL_INFO)
+ sizeof (HID_DEVICE_ATTRIBUTES); controlInfo = (PHIDMINI_CONTROL_INFO)ExAllocatePoolWithTag(PagedPool,bufferSize,TAG_HIDMINI_CONTROL_INFO);
if (!controlInfo )
{
KdPrint(("ExAllocatePoolWithTag for PHIDMINI_CONTROL_INFO failed\n")); return false ;
}
controlInfo->ReportId = ReportID;
controlInfo->ControlCode=CtlCode;
Status= KernelDeviceIoControlsySynchronize(IOCTL_HID_GET_FEATURE,DriverObject,DeviceObject,NULL,0,(PVOID)controlInfo,bufferSize);
if(!NT_SUCCESS(Status))
{
KdPrint(("KbFilter: failed IOCTL_HID_GET_FEATURE\n"));
if(controlInfo!=NULL)
{
ExFreePoolWithTag(controlInfo,TAG_HIDMINI_CONTROL_INFO);
}
return false;
}else
{
KdPrint(("KbFilter: success IOCTL_HID_GET_FEATURE\n"));
}
KdPrint(("KbFilter: leave SendHidRequests\n"));
KdPrint(("==============================================\n\n"));
if(controlInfo!=NULL)
{
ExFreePoolWithTag(controlInfo,TAG_HIDMINI_CONTROL_INFO);
}
return true;
}
第一段括号没括上 上面是第一段的重发
用的是 setupapiHidD_GetHidGuid
SetupDiGetClassDevs
OpenDeviceInterface
SetupDiGetDeviceInterfaceDetailHidD_GetPreparsedData
HidP_GetCaps
用户模式部分访问hid设备部分就是 wdk 里vhidmini这个例子自带的
hid手柄 是从vhidmini改的 只改了描述符为手柄 HidD_GetPreparsedData 这个函数
reactos用的发送
IOCTL_HID_GET_COLLECTION_INFORMATION
和 IOCTL_HID_GET_COLLECTION_DESCRIPTOR 来实现msdn 也说内核下访问hid设备 用这两个 于是从reactos里抄过来
但是不知为何 缓冲区是空的
发送 IOCTL_HID_GET_COLLECTION_INFORMATION
返回的 缓冲区 HID_COLLECTION_INFORMATION hci; 里面是空的
以至于后面的都进行不下去