Esempio n. 1
0
/**
* 初始化文件日志。4个参数
* 在使用该日志模块时在写日志之前要调用该函数进行初始化,在中间任何地方都可以对日志文件进行写入日志信息,当写完日志后,不再调用该函数写日志,那么要调用LogUninitialize进行清理。
*/
void LogInitialize(ULONG loglevel,WCHAR* logfilename,LONGLONG filesize,USHORT strategy)
{
	size_t flength;
	NTSTATUS ntStatus = RtlStringCchLengthW(logfilename,(MAX_PATH-2),&flength);
	if(!NT_SUCCESS(ntStatus) )
	{
		KdPrint( ("Filename too long!\n") );
		return;
	}

	KdPrint( ("Filename length:%d\n",flength) );

	//将文件名记录在g_LogFileName中,注意Unicode_String不是以0为结束,以Length作为计算标准
	g_logFileName.Buffer = (PWSTR)ExAllocatePool(NonPagedPool,MAX_PATH*sizeof(WCHAR));//申请双倍内存
	RtlZeroMemory(g_logFileName.Buffer,MAX_PATH*sizeof(WCHAR));//清0,为了下面的操作顺利
	g_logFileName.MaximumLength = MAX_PATH*sizeof(WCHAR);
	RtlCopyMemory(g_logFileName.Buffer,logfilename,flength*sizeof(WCHAR));
	g_logFileName.Length = flength*sizeof(WCHAR);

	KdPrint( ("Filename:%wZ\n",&g_logFileName) );

	g_logLevel = loglevel;
	g_logFileMaxSize = filesize;
	g_logWriteTime = 0;

	g_logStrategy = strategy;

	//初始化处理互斥体
	KeInitializeMutex(&g_logMutex,0);
	KdPrint( ("Log Init Sucsess!\n") );
}
Esempio n. 2
0
//////////////////////////////////////////////////////////////////////////
//
//	Event log
//
static
VOID
_WriteLogErrorEntry(
	IN PDEVICE_OBJECT			DeviceObject,
	IN PLSU_ERROR_LOG_ENTRY		LogEntry
){
	PIO_ERROR_LOG_PACKET errorLogEntry;
	WCHAR					strBuff[16];
	NTSTATUS				status;
	ULONG					stringOffset;
	ULONG_PTR				stringLen;
	ULONG					idx_dump;

	//
	//	Parameter to unicode string
	//
	ASSERT(LogEntry->DumpDataEntry <= LSU_MAX_ERRLOG_DATA_ENTRIES);
	ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

	status = RtlStringCchPrintfW(strBuff, 16, L"%u", LogEntry->Parameter2);
	if(!NT_SUCCESS(status)) {
		KDPrint(1, ("RtlStringCchVPrintfW() failed.\n"));
		return;
	}

	status = RtlStringCchLengthW(strBuff, 16, &stringLen);
	if(!NT_SUCCESS(status)) {
		KDPrint(1, ("RtlStringCchLengthW() failed.\n"));
		return;
	}

	//
	//	Translate unicode length into byte length including NULL termination.
	//

	stringLen = ( stringLen + 1 ) * sizeof(WCHAR);
	stringOffset = FIELD_OFFSET(IO_ERROR_LOG_PACKET, DumpData) + LogEntry->DumpDataEntry * sizeof(ULONG);


	errorLogEntry = (PIO_ERROR_LOG_PACKET)
					IoAllocateErrorLogEntry(
									DeviceObject,
									(sizeof(IO_ERROR_LOG_PACKET) +
									(LogEntry->DumpDataEntry * sizeof(ULONG)) +
									(UCHAR)stringLen));
	if(errorLogEntry == NULL) {
		KDPrint(1, ("Could not allocate error log entry.\n"));
		ASSERT(FALSE);
		return ;
	}

	errorLogEntry->ErrorCode = LogEntry->ErrorCode;
	errorLogEntry->MajorFunctionCode = LogEntry->MajorFunctionCode;
	errorLogEntry->IoControlCode = LogEntry->IoctlCode;
	errorLogEntry->EventCategory;
	errorLogEntry->SequenceNumber = LogEntry->SequenceNumber;
	errorLogEntry->RetryCount = (UCHAR) LogEntry->ErrorLogRetryCount;
	errorLogEntry->UniqueErrorValue = LogEntry->UniqueId;
	errorLogEntry->FinalStatus = STATUS_SUCCESS;
	errorLogEntry->DumpDataSize = LogEntry->DumpDataEntry * sizeof(ULONG);
	for(idx_dump=0; idx_dump < LogEntry->DumpDataEntry; idx_dump++) {
		errorLogEntry->DumpData[idx_dump] = LogEntry->DumpData[idx_dump];
	}

	errorLogEntry->NumberOfStrings = 1;
	errorLogEntry->StringOffset = (USHORT)stringOffset;
	RtlCopyMemory((PUCHAR)errorLogEntry + stringOffset, strBuff, stringLen);

	IoWriteErrorLogEntry(errorLogEntry);

	return;
}
Esempio n. 3
0
/**
* 写日志函数
* @param iLevel:ULONG,要写入日志信息的等级,请参考LogConst.h文件内等级。
* @param format:NTSTRSAFE_PSTR*,输入信息的格式,此格式参考printf。
* @param ...:变参,参考printf,要写入的信息。
* 写日志信息接口,写日志信息大小请不要超过规定长度的大小!最大暂时为256字节!!
*/
void _cdecl WriteSysLog(ULONG iLevel, NTSTRSAFE_PWSTR format,...)
{
	//判断记录日志级别
	if(iLevel > g_logLevel)
		return;

	//获得互斥体,在下面的调用中,所有的函数退出部分都要进行释放互斥体
	KeWaitForSingleObject(&g_logMutex, Executive, KernelMode, FALSE, NULL);
	
	HANDLE logfile;
	OBJECT_ATTRIBUTES   objectAttributes;
	IO_STATUS_BLOCK		ioStatus;
	NTSTATUS ntStatus;
	
	InitializeObjectAttributes(&objectAttributes,&g_logFileName,OBJ_CASE_INSENSITIVE,NULL, NULL);

	
	ntStatus = ZwCreateFile(&logfile,FILE_READ_ATTRIBUTES | FILE_APPEND_DATA | SYNCHRONIZE,
				&objectAttributes,&ioStatus,NULL,FILE_ATTRIBUTE_NORMAL,
				FILE_SHARE_READ|FILE_SHARE_WRITE,FILE_OPEN_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0);
	if(!NT_SUCCESS(ntStatus) )
	{
		KeReleaseMutex(&g_logMutex,FALSE);
		KdPrint( ("Strategy:%d:Init Open file error!\n",g_logStrategy) );
		return;
	}

	//判断文件大小处理的函数
	if(g_logWriteTime >= CHECK_TIME)
	{
		if(g_logStrategy == 1)
		{
			ntStatus = CheckLogFileSizeAndReCreateLogFile(&g_logFileName,1,logfile);

			if(!NT_SUCCESS(ntStatus) )
			{
				KeReleaseMutex(&g_logMutex,FALSE);
				KdPrint( ("Strategy:%d:Init Open file error!\n",g_logStrategy) );
				return;
			}
		}

		g_logWriteTime = 0;
	}

	TIME_FIELDS ctime;
	ctime = GetLocalTime();
	ULONG pid = (ULONG)PsGetCurrentProcessId();
	PWCHAR ptype;

	switch(iLevel)
	{
		case LOG_TYPE_ERROR:	ptype = L"ERROR";break;
		case LOG_TYPE_WARN:		ptype = L"WARNING";break;
		case LOG_TYPE_INFO:		ptype = L"INFO";break;
		default:				ptype = L"DEBUG";break;
	}
    WCHAR strTemp[MAX_INFO_LENGTH];
    RtlZeroMemory(strTemp, MAX_INFO_LENGTH);
    NTSTRSAFE_PWSTR pinfo = strTemp;

 	va_list args; 
    va_start(args,format); 
	ntStatus =::RtlStringCchVPrintfW(pinfo,MAX_INFO_LENGTH*sizeof(WCHAR),format,args);
	if( !NT_SUCCESS(ntStatus) )
	{
		DbgPrint( ("Log info conversion error1!\n") );
		ZwClose(logfile);
		KeReleaseMutex(&g_logMutex,FALSE);
		//在函数所有的出口释放互斥体
		return;
	}
    va_end(args); 

	WCHAR cinfo[MAX_INFO_LENGTH*2];
	RtlZeroMemory(cinfo,MAX_INFO_LENGTH*2*sizeof(WCHAR));//清0,为了下面的操作顺利
	ntStatus = RtlStringCchPrintfW(cinfo,MAX_INFO_LENGTH*2*sizeof(WCHAR), L"%04d-%02d-%02d %02d:%02d:%02d.%03d\t%d\t%s\t%s\r\n", ctime.Year, ctime.Month, ctime.Day, 
		ctime.Hour, ctime.Minute, ctime.Second, ctime.Milliseconds,pid,ptype,pinfo);
	if( !NT_SUCCESS(ntStatus) )
	{
		DbgPrint( ("Log info conversion error2!\n") );
		//在函数所有的出口释放互斥体
		ZwClose(logfile);
		KeReleaseMutex(&g_logMutex,FALSE);
		return;
	}

	size_t length;
	ntStatus = RtlStringCchLengthW(cinfo,MAX_INFO_LENGTH*2,&length);
	if( !NT_SUCCESS(ntStatus) )
	{
		DbgPrint( ("Log info conversion error3!\n") );
		//在函数所有的出口释放互斥体
		ZwClose(logfile);
		KeReleaseMutex(&g_logMutex,FALSE);
		return;
	}
	ntStatus = ZwWriteFile(logfile,NULL,NULL,NULL,&ioStatus,cinfo,length*sizeof(WCHAR),NULL,NULL);
	if( !NT_SUCCESS(ntStatus) )
	{
		DbgPrint( ("Write log error!\n") );
		ZwClose(logfile);
		//在函数所有的出口释放互斥体
		KeReleaseMutex(&g_logMutex,FALSE);
		return;
	}
	g_logWriteTime ++;//增加写入次数

	ZwClose(logfile);
	KeReleaseMutex(&g_logMutex,FALSE);
	//KdPrint( ("write log successful!\n") );
}
Esempio n. 4
0
// handles operations that must be performed when an application requests access to a device.
VOID vJoy_EvtDeviceFileCreate(
  __in  WDFDEVICE Device,
  __in  WDFREQUEST Request,
  __in  WDFFILEOBJECT FileObject
)
{
		WDFFILEOBJECT FileObj;
		PCUNICODE_STRING pName;
		UNICODE_STRING TmpUstr;
		NTSTATUS status = STATUS_SUCCESS;
		int  id=0;
		WCHAR RefStr[100];
		PFILEOBJECT_EXTENSION pExtension=NULL;
		PDEVICE_EXTENSION    pDevContext = NULL;
		PRPDO_DEVICE_DATA	pPdoData=NULL;
		size_t len;
		DWORD_PTR ProcessId;

	    PAGED_CODE ();
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "Entered vJoy_EvtDeviceFileCreate\n");


		// Get file object then get its filename
		FileObj = WdfRequestGetFileObject(Request);
		if (!FileObj)
			goto going_out;
		pName = WdfFileObjectGetFileName(FileObj);
		if (!pName)
			goto going_out;

		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: File name=%wZ\n", pName);

		// Extract id from interface number
		status = RtlStringCchLengthW(VJOY_INTERFACE, 100, &len);
		if (!NT_SUCCESS(status))
			goto going_out;
		status = RtlStringCchCopyNW(RefStr, 100, pName->Buffer+len+1,4);	// Copy the numeric part of the string (000)
		if (!NT_SUCCESS(status))
			goto going_out;
		RtlInitUnicodeString(&TmpUstr, RefStr);								// Convert "000" to UNICODE_STRING
		status = RtlUnicodeStringToInteger(&TmpUstr, 10, &id);				// Convert "000" to integer (0)
		if (!NT_SUCCESS(status))
			goto going_out;

		if (id>0)
		{
			// Verify that this interface has a corresponding device
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: ID=%d\n", id);
			pPdoData = PdoGetData(Device);
			pDevContext = GetDeviceContext(pPdoData->hParentDevice);
			if (!pDevContext)
				goto going_out;
			if (!pDevContext->positions[id - 1])
				goto going_out;

			// Get the file object context space
			// Test that this interface is not in use
			// and store there the parent (Raw PDO) context
			pExtension = GetFileObjectContext(FileObject);
			if (!pExtension)
				goto going_out;
			pExtension->pParentRawDeviceContext = pPdoData;
			if (pPdoData->UsedInterfacesMask & (1 << (id - 1)))
			{
				WdfRequestComplete(Request, STATUS_ACCESS_DENIED);
				ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
				TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d Failed (Access Denied)\n", ProcessId);
				return;
			}

			///// This is a successful file creation - Now record the file details

			// vJoy Device ID
			else
				pPdoData->UsedInterfacesMask |= 1 << (id - 1);

			// Put id in file object context space 
			pExtension->id = id; // Update

			// Get the id of the calling process
			ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
			pExtension->CallingProcessId = (DWORD)(ProcessId & 0xFFFFFFFF);
			TraceEvents(TRACE_LEVEL_WARNING, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d\n", pExtension->CallingProcessId);

			// Put the file object in the FDO extension
			pDevContext->DeviceFileObject[id - 1] = FileObject;

			// Activate FFB Queues
			FfbActiveSet(TRUE, id, pDevContext);


			WdfRequestComplete(Request, status);
			return;

		} // if (id>0)

		// Case of General purpose and non device-specific Interface
		else // if (id<1)
		{
			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate(2nd case): ID=%d\n", id);
#if 0
			pPdoData = PdoGetData(Device);
			pDevContext = GetDeviceContext(pPdoData->hParentDevice);
			if (!pDevContext)
				goto going_out;

			TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate(2nd case): Completing Request\n");

#endif // 0
			WdfRequestComplete(Request, status);
			return;
		}; // if (id<1)

	going_out:
		ProcessId = (DWORD_PTR)PsGetCurrentProcessId();
		TraceEvents(TRACE_LEVEL_INFORMATION, DBG_INIT, "vJoy_EvtDeviceFileCreate: PID=%d Failed (Invalid Handle)\n", ProcessId);
		WdfRequestComplete(Request, STATUS_INVALID_HANDLE);
}
// 并行处理
VOID CY001Drv::DeviceIoControlParallel(IN WDFQUEUE  Queue,
						IN WDFREQUEST  Request,
						IN size_t  OutputBufferLength,
						IN size_t  InputBufferLength,
						IN ULONG  IoControlCode)
{
	NTSTATUS status = STATUS_SUCCESS;
	ULONG ulRetLen = 0;

	size_t size = 0;
	void* pBufferInput = NULL;
	void* pBufferOutput = NULL;

	KDBG(DPFLTR_INFO_LEVEL, "[DeviceIoControlParallel] CtlCode:0x%0.8X", IoControlCode);

	// 取得输入缓冲区,判断其有效性
	if(InputBufferLength){
		status = WdfRequestRetrieveInputBuffer(Request, InputBufferLength, &pBufferInput, &size);
		if(status != STATUS_SUCCESS || pBufferInput == NULL || size < InputBufferLength){
			WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
			return;
		}
	}

	// 取得输出缓冲区,判断其有效性
	if(OutputBufferLength){
		status = WdfRequestRetrieveOutputBuffer(Request, OutputBufferLength, &pBufferOutput, &size);
		if(status != STATUS_SUCCESS || pBufferOutput == NULL || size < OutputBufferLength){
			WdfRequestComplete(Request, STATUS_INVALID_PARAMETER);
			return;
		}
	}

	//
	// 下面是主处理过程。
	//
	switch(IoControlCode)
	{
		// 取得驱动的版本信息
	case IOCTL_GET_DRIVER_VERSION:
		{
			PDRIVER_VERSION pVersion = (PDRIVER_VERSION)pBufferOutput;
			ULONG length;
			char tcsBuffer[120];
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_GET_DRIVER_VERSION");

			if(OutputBufferLength < sizeof(DRIVER_VERSION)){
				status = STATUS_BUFFER_TOO_SMALL;
				break;
			}

			pVersion->DriverType = DR_WDF;
			pVersion->FirmwareType = FW_NOT_CY001;
			ulRetLen = sizeof(DRIVER_VERSION);// 告示返回长度

			// 根据String描述符,判断Firmware代码是否已经被加载。
			GetStringDes(2, 0, tcsBuffer, 120, &length);

			if(length){
				WCHAR* pCyName = L"CY001 V";
				size_t len;
				int nIndex;

				if(length < 8)
					break;

				RtlStringCchLengthW(pCyName, 7, &len);
				for(nIndex = 0; nIndex < len; nIndex++){
					if(pCyName[nIndex] != ((WCHAR*)tcsBuffer)[nIndex])
						break;
				}

				if(nIndex == len)
					pVersion->FirmwareType = FW_CY001; // 完全相符,说明新版Firmware已经加载到开发板。
			}
			break;
		}
		
		// 收到App发送过来的一个同步Request,我们应该把它保存到同步Queue中,等到有同步事件发生的时候再从Queue中取出并完成。
	case IOCTL_USB_SYNC:
		KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SYNC");
		status = WdfRequestForwardToIoQueue(Request, m_hAppSyncManualQueue);

		// 直接返回,不调用WdfRequestComplete函数。
		// 请求者将不会为此而等待;请求的完成在将来的某个时刻。
		// 这就是所谓的异步处理之要义了。
		if(NT_SUCCESS(status))
			return;
		break;

		// 清空同步队列中的所有请求
	case IOCTL_USB_SYNC_RELEASE:
		KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SYNC");
		ClearSyncQueue();
		break;

		// 应用程序退出,取消所有被阻塞的请求。
	case IOCTL_APP_EXIT_CANCEL: 
			
		// 取消USB设备的所有IO操作。它将连带取消所有Pipe的IO操作。
		//WdfIoTargetStop(WdfUsbTargetDeviceGetIoTarget(m_hUsbDevice), WdfIoTargetCancelSentIo);
		break;

		// 取得当前的配置号.总是设置为0,因为在WDF框架中,0以外的配置是不被支持的。
	case IOCTL_USB_GET_CURRENT_CONFIG:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_CURRENT_CONFIG");
			if(InputBufferLength < 4){
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			*(PULONG)pBufferInput = 0;// 直接赋值0,即总是选择0号配置。也可以发送URB到总线获取当前配置选项。
			ulRetLen = sizeof(ULONG);
			break;
		}

	case IOCTL_USB_ABORTPIPE:
		{
			ULONG pipenum = *((PULONG) pBufferOutput);
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_ABORTPIPE");

			status = AbortPipe(pipenum);
		}      
		break;

		// 获取Pipe信息
	case IOCTL_USB_GET_PIPE_INFO:
		{
			// 遍历获取Pipe信息,复制到输出缓冲中。
			BYTE byCurSettingIndex = 0;
			BYTE byPipeNum = 0;
			BYTE index;
			USB_INTERFACE_DESCRIPTOR  interfaceDescriptor;
			WDF_USB_PIPE_INFORMATION  pipeInfor;

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_PIPE_INFO");

			// 取得Pipe数。根据Pipe数计算缓冲区长度
			byCurSettingIndex = WdfUsbInterfaceGetConfiguredSettingIndex(m_hUsbInterface); 
			WdfUsbInterfaceGetDescriptor(m_hUsbInterface, byCurSettingIndex, &interfaceDescriptor);
			byPipeNum = WdfUsbInterfaceGetNumConfiguredPipes(m_hUsbInterface);		

			if(OutputBufferLength < byPipeNum * sizeof(pipeInfor)){
				status = STATUS_BUFFER_TOO_SMALL; // 缓冲区不足
			}else{

				ulRetLen = byPipeNum*sizeof(pipeInfor);

				// 遍历获取全部管道信息,拷贝到输出缓冲中。
				// 应用程序得到输出缓冲的时候,也应该使用WDF_USB_PIPE_INFORMATION结构体解析缓冲区。
				for(index = 0; index < byPipeNum; index++)
				{
					WDF_USB_PIPE_INFORMATION_INIT(&pipeInfor);
					WdfUsbInterfaceGetEndpointInformation(m_hUsbInterface, byCurSettingIndex, index, &pipeInfor);
					RtlCopyMemory((PUCHAR)pBufferOutput + index*pipeInfor.Size, &pipeInfor, sizeof(pipeInfor));
				}
			}
		}

		break;

		// 获取设备描述符
	case IOCTL_USB_GET_DEVICE_DESCRIPTOR:
		{
			USB_DEVICE_DESCRIPTOR  UsbDeviceDescriptor;
			WdfUsbTargetDeviceGetDeviceDescriptor(m_hUsbDevice, &UsbDeviceDescriptor);
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_DEVICE_DESCRIPTOR");

			// 判断输入缓冲区的长度是否足够长
			if(OutputBufferLength < UsbDeviceDescriptor.bLength)
				status = STATUS_BUFFER_TOO_SMALL;
			else{
				RtlCopyMemory(pBufferOutput, &UsbDeviceDescriptor, UsbDeviceDescriptor.bLength);
				ulRetLen = UsbDeviceDescriptor.bLength;
			}

			break;
		}

		// 获取字符串描述符
	case IOCTL_USB_GET_STRING_DESCRIPTOR:
		{
			PGET_STRING_DESCRIPTOR Input = (PGET_STRING_DESCRIPTOR)pBufferInput;
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_STRING_DESCRIPTOR");
			status = GetStringDes(Input->Index, Input->LanguageId, pBufferOutput, OutputBufferLength, &ulRetLen);
			
			// 由字符长度调整为字节长度
			if(NT_SUCCESS(status) && ulRetLen > 0)
				ulRetLen *= (sizeof(WCHAR)/sizeof(char));
			break;
		}

		// 获取配置描述信息。
	case IOCTL_USB_GET_CONFIGURATION_DESCRIPTOR:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_CONFIGURATION_DESCRIPTOR");

			// 首先获得配置描述符的长度。
			status = WdfUsbTargetDeviceRetrieveConfigDescriptor(m_hUsbDevice, NULL, (USHORT*)&size);
			if(!NT_SUCCESS(status) && status != STATUS_BUFFER_TOO_SMALL)
				break;

			// 输出缓冲区不够长
			if(OutputBufferLength < size)
				break;

			// 正式取得配置描述符。
			status = WdfUsbTargetDeviceRetrieveConfigDescriptor(m_hUsbDevice, pBufferOutput, (USHORT*)&size);
			if(!NT_SUCCESS(status))
				break;

			ulRetLen = size;
			break;
		}

		// 根据可选值配置接口
	case IOCTL_USB_SET_INTERFACE:
		{
			BYTE byAlterSetting = *(BYTE*)pBufferInput;
			BYTE byCurSetting = WdfUsbInterfaceGetConfiguredSettingIndex(m_hUsbInterface); // 当前Alternate值

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SETINTERFACE");

			if(InputBufferLength < 1 || OutputBufferLength < 1)
			{
				status = STATUS_BUFFER_TOO_SMALL;
				break;
			}
			
			// 如果传入的可选值与当前的不同,则重新配置接口;
			// 否则直接返回。
			if(byCurSetting != byAlterSetting)
			{
				WDF_USB_INTERFACE_SELECT_SETTING_PARAMS par;
				WDF_USB_INTERFACE_SELECT_SETTING_PARAMS_INIT_SETTING(&par, byAlterSetting);
				status = WdfUsbInterfaceSelectSetting(m_hUsbInterface, NULL, &par);
			}

			*(BYTE*)pBufferOutput = byCurSetting;
			break;
		}

		// 固件Rest。自定义命令,与Port Rest是两码事。
	case IOCTL_USB_FIRMWRAE_RESET:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_FIRMWRAE_RESET");
			if(InputBufferLength < 1 || pBufferInput == NULL)
				status = STATUS_INVALID_PARAMETER;
			else
				status = FirmwareReset(*(char*)pBufferInput);

			break;
		}

		// 重置USB总线端口
	case IOCTL_USB_PORT_RESET:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PORT_RESET");			
			WdfUsbTargetDeviceResetPortSynchronously(m_hUsbDevice);
			break;
		}

		// 管道重置
	case IOCTL_USB_PIPE_RESET:
		{
			UCHAR uchPipe;
			WDFUSBPIPE pipe = NULL;

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PIPE_RESET");			

			if(InputBufferLength < 1){
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			// 根据ID找到对应的Pipe
			uchPipe = *(UCHAR*)pBufferInput;
			pipe = WdfUsbInterfaceGetConfiguredPipe(m_hUsbInterface, uchPipe, NULL);
			if(pipe == NULL){ 
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			status = WdfUsbTargetPipeResetSynchronously(pipe, NULL, NULL);
			break;
		}

		// 中断管道,放弃管道当前正在进行的操作
	case IOCTL_USB_PIPE_ABORT:
		{
			UCHAR uchPipe;
			WDFUSBPIPE pipe = NULL;

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_PIPE_ABORT");

			if(InputBufferLength < 1){
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			// 根据ID找到对应的Pipe
			uchPipe = *(UCHAR*)pBufferInput;
			pipe = WdfUsbInterfaceGetConfiguredPipe(m_hUsbInterface, uchPipe, NULL);
			if(pipe == NULL){ 
				status = STATUS_INVALID_PARAMETER;
				break;
			}
			
			status = WdfUsbTargetPipeAbortSynchronously(pipe, NULL, NULL);
			break;
		}

		// 取得驱动错误信息,驱动总是把最后一次发现的错误保存在设备对象的环境块中。
		// 这个逻辑虽然实现了,但目前的版本中,应用程序并没有利用这个接口。
	case IOCTL_USB_GET_LAST_ERROR:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_GET_LAST_ERROR");

			if (OutputBufferLength >= sizeof(ULONG))
				*((PULONG)pBufferOutput) = m_ulLastUSBErrorStatusValue;
			else
				status = STATUS_BUFFER_TOO_SMALL;

			ulRetLen = sizeof(ULONG);
			break;
		}

		// Clear feature命令
	case IOCTL_USB_SET_CLEAR_FEATURE:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_USB_SET_CLEAR_FEATURE");
			status = UsbSetOrClearFeature(Request);
			break;
		}

		// 为USB设备加载固件程序。带有偏移量参数,用这个分支;不带偏移量,可用下一个分支。
		// 带偏移量的情况下,固件代码是一段一段地加载;
		// 不带偏移量的情况,固件代码作为一整块一次性被加载。
	case IOCTL_FIRMWARE_UPLOAD_OFFSET:
		{
			void* pData = pBufferOutput;
			WORD offset = 0;

			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_UPLOAD_OFFSET");

			if(InputBufferLength < sizeof(WORD)){
				status = STATUS_INVALID_PARAMETER;
				break;
			}

			offset = *(WORD*)pBufferInput;
			status = FirmwareUpload((PUCHAR)pData, OutputBufferLength, offset);
			break;
		}

		// 为USB设备加载固件程序。
	case IOCTL_FIRMWARE_UPLOAD:
		{
			void* pData = pBufferOutput;
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_UPLOAD");
			status = FirmwareUpload((PUCHAR)pData, InputBufferLength, 0);
			break;
		}

		// 读取开发板设备的RAM内容。RAM也就是内存。
		// 每次从同一地址读取的内容可能不尽相同,开发板中固件程序在不断运行,RAM被用来储数据(包括临时数据)。
	case IOCTL_FIRMWARE_READ_RAM:
		{
			KDBG(DPFLTR_INFO_LEVEL, "IOCTL_FIRMWARE_READ_RAM");
			status = ReadRAM(Request, &ulRetLen);// inforVal中保存读取的长度
			break;
		}

		// 其他的请求
	default:
		{
			// 一律转发到SerialQueue中去。			
			WdfRequestForwardToIoQueue(Request, m_hIoCtlSerialQueue);

			// 命令转发之后,这里必须直接返回,千万不可调用WdfRequestComplete函数。
			// 否则会导致一个Request被完成两次的错误。
			return;
		}
	}

	// 完成请求
	WdfRequestCompleteWithInformation(Request, status, ulRetLen);
}
Esempio n. 6
0
VOID DokanPrintToSysLog(__in PDRIVER_OBJECT DriverObject,
                        __in UCHAR MajorFunctionCode, __in NTSTATUS MessageId,
                        __in NTSTATUS Status, __in LPCTSTR Format,
                        __in va_list Args) {
  NTSTATUS status = STATUS_SUCCESS;
  PIO_ERROR_LOG_PACKET packet = NULL;
  WCHAR *message = NULL;
  size_t messageCapacity = DOKAN_LOG_MAX_CHAR_COUNT;
  size_t messageCharCount = 0;
  size_t messageCharsWritten = 0;
  size_t packetCount = 0;
  size_t i = 0;
  UCHAR packetCharCount = 0;
  UCHAR packetSize = 0;

  __try {
    message = ExAllocatePool(sizeof(WCHAR) * messageCapacity);
    if (message == NULL) {
      DDbgPrint("Failed to allocate message of capacity %d\n", messageCapacity);
      __leave;
    }

    status = RtlStringCchVPrintfW(message, messageCapacity, Format, Args);
    if (status == STATUS_BUFFER_OVERFLOW) {
      // In this case we want to at least log what we can fit.
      DDbgPrint("Log message was larger than DOKAN_LOG_MAX_CHAR_COUNT."
                " Format: %S\n", Format);
    } else if (status != STATUS_SUCCESS) {
      DDbgPrint("Failed to generate log message with format: %S; status: %x\n",
                Format, status);
      __leave;
    }

    status = RtlStringCchLengthW(message, messageCapacity, &messageCharCount);
    if (status != STATUS_SUCCESS) {
      DDbgPrint("Failed to determine message length, status: %x\n", status);
      __leave;
    }

    packetCount = messageCharCount / DOKAN_LOG_MAX_PACKET_NONNULL_CHARS;
    if (messageCharCount % DOKAN_LOG_MAX_PACKET_NONNULL_CHARS != 0) {
      ++packetCount;
    }

    for (i = 0; i < packetCount; i++) {
      packetCharCount = (UCHAR)min(messageCharCount - messageCharsWritten,
                                   DOKAN_LOG_MAX_PACKET_NONNULL_CHARS);
      packetSize = sizeof(IO_ERROR_LOG_PACKET)
          + sizeof(WCHAR) * (packetCharCount + 1);
      packet = IoAllocateErrorLogEntry(DriverObject, packetSize);
      if (packet == NULL) {
        DDbgPrint("Failed to allocate packet of size %d\n", packetSize);
        __leave;
      }
      RtlZeroMemory(packet, packetSize);
      packet->MajorFunctionCode = MajorFunctionCode;
      packet->NumberOfStrings = 1;
      packet->StringOffset =
          (USHORT)((char *)&packet->DumpData[0] - (char *)packet);
      packet->ErrorCode = MessageId;
      packet->FinalStatus = Status;
      RtlCopyMemory(&packet->DumpData[0], message + messageCharsWritten,
                    sizeof(WCHAR) * packetCharCount);
      IoWriteErrorLogEntry(packet); // Destroys packet.
      packet = NULL;
      messageCharsWritten += packetCharCount;
    }
  } __finally {
    if (message != NULL) {
      ExFreePool(message);
    }
  }
}